当前位置: 首页 > 知识库问答 >
问题:

按步骤对数组中的数字进行分组值更改

司空劲
2023-03-14

我有一个类似[101、107、106、199、204、205、207、306、310、312、312、314、317、318、380、377、379、382、466、469、471、472、557、559、562、566、569…]

在这个数组中,在几个整数之后,值将发生阶跃变化。(如[101107106]和[199204,…])或者换句话说,数组由整数组组成,每组的值以未知均值为中心。但我不知道总共有多少个组,每个组中的整数数量是不确定的。

我如何将每个步骤中的整数分组到不同的数组中。

谢啦

共有3个答案

程俊健
2023-03-14

从您发布的代码中可以看出,当abs(array[i]-array[i 1])时会发生一个步骤

final = []
current = []   
arr = [101, 107, 106, 199, 204, 205, 207, 306, 310, 312, 312, 314, 317, 318, 380, 377, 379, 382, 466, 469, 471, 472, 557, 559, 562, 566, 569]
for i in range(len(arr)-1):
   if abs(arr[i] - arr[i+1]) > 6:
      current.append(arr[i])
      final.append(current)
      current = []
   else:
       current.append(arr[i])

输出:

[[101, 107, 106], [199, 204, 205, 207], [306, 310, 312, 312, 314, 317, 318], [380, 377, 379, 382], [466, 469, 471, 472]]
毛淳
2023-03-14

我尝试做我在评论中建议的事情。我认为这将为更普遍的问题提供一个很好的解决方案,但我警告说,我没有考虑所有边缘情况或考虑这里的算法复杂性。

import numpy as np

# function to initialize clusters
def init_clusters(x, num_elements_per_cluster=3):
    # initialize clusters by splitting into n groups
    x.sort()  # sort the list
    nclusters = len(x) / num_elements_per_cluster
    clusters = {i: {'values': []} for i in range(nclusters)}

    # assign to clusters (helps that list is sorted)
    for i in range(len(x)):
        index = min(i/num_elements_per_cluster, nclusters-1)
        clusters[index]['values'].append(x[i])

    # compute variance
    for index in clusters:
        clusters[index]['var'] = np.var(clusters[index]['values'])

    return clusters

def get_avg_var(clusters):
    total_var = 0.0
    denom = 0.0
    for index in clusters:
        total_var += clusters[index]['var'] * len(clusters[index]['values'])
        denom += len(clusters[index]['values'])
    return total_var / denom  # possible div by 0, but shouldn't happen

def assign_value_to_cluster(clusters, value):
    """
    add value to a cluster such that results in the lowest variance
    """
    new_cluster_vars = []
    indices = []
    for index in clusters:
        new_cluster_vars.append(np.var(clusters[index]['values'] + [value]))
        indices.append(index)

    index_min_new_cluster_var = indices[np.argmin(new_cluster_vars)]
    clusters[index_min_new_cluster_var]['values'].append(value)
    # update the variances
    clusters[index_min_new_cluster_var]['var'] = new_cluster_vars[index_min_new_cluster_var]


def purify(clusters):
    curr_var = get_avg_var(clusters)
    prev_var = curr_var*10
    max_iter = 1000
    iter_count = 0
    while(curr_var < prev_var):
        if iter_count > max_iter:
            break

        prev_var = curr_var

        # start with the cluster with the highest variance
        sorted_vars = sorted(
            [{'index': i, 'var': clusters[i]['var']} for i in clusters],
            key=lambda x: x['var'], 
            reverse=True
        )
        highest_var_index = sorted_vars[0]['index']

        vals = clusters[highest_var_index]['values']
        if len(vals) > 2:
            # find the element that when removed will minimize the variance of this cluster
            dropout_variance = [np.var([vals[j] for j in range(len(vals)) if j != i]) for i in range(len(vals))]
            index_to_drop = np.argmin(dropout_variance)
            value_to_reassign = clusters[highest_var_index]['values'].pop(index_to_drop)
            # update the variances
            clusters[highest_var_index]['var'] = dropout_variance[index_to_drop]
            assign_value_to_cluster(clusters, value_to_reassign)
        else:
            # break this cluster and assign values to others
            clusters.pop(highest_var_index)
            for val in vals:
                assign_value_to_cluster(clusters, val)

        curr_var = get_avg_var(clusters)
        print "after iter %04d: %04.2f" % (iter_count, curr_var) 
        iter_count += 1

    return clusters

在提供的样本数据上运行算法:

# vector x of values that we want to cluster
x = [
    101, 107, 106, 199, 204, 205, 207, 306, 310, 312,
    312, 314, 317, 318, 380, 377, 379, 382, 466, 469,
    471, 472, 557, 559, 562, 566, 569
]

clusters = init_clusters(x)
final_clusters = purify(clusters)

# print values of the final clusters
[final_clusters[y]['values'] for y in final_clusters]

输出:

[[101, 106, 107],
 [204, 205, 207, 199],
 [306, 310],
 [312, 312, 314],
 [317, 318],
 [379, 380, 382, 377],
 [466, 469, 471, 472],
 [557, 559],
 [562, 566, 569]]

编辑:修复了get\u avg\u var()中的一个错误,并意识到我没有更新集群方差。这对初始化很敏感,但通常会提供合理的集群。也就是说,您可以定义自己的优化参数(而不是像我那样使用平均聚类方差)。

颜思淼
2023-03-14

你可以试试这个:确定每对连续数字的差异,并从中确定平均差异。

nums = [101, 107, 106, 199, 204, 205, 207, 306, 310, 312, 312, 314, 317, 318, 
        380, 377, 379, 382, 466, 469, 471, 472, 557, 559, 562, 566, 569]
pairs = list(zip(nums, nums[1:]))
diffs = [abs(x-y) for x, y in pairs]
avg_diff = sum(diffs) / len(diffs)  # ~ 18.31

现在,您可以根据与前一个数字的差值是否低于或高于该平均值来对这些数字进行分组:

groups = [[nums[0]]]          # first group already has first number
for (x, y), d in zip(pairs, diffs):
    if d < avg_diff:
        groups[-1].append(y)  # add to last group
    else:
        groups.append([y])    # start new group

或者,如果您更喜欢跨越三行的单行代码,这可能适合您:

groups = [functools.reduce(lambda A, b: A+(b[1],) if A else b, group, None) 
          for key, group in itertools.groupby(zip(nums, nums[1:]), 
                  key=lambda t: abs(t[0]-t[1]) < 18.3) if key]

示例的结果如下:

[[101, 107, 106],
 [199, 204, 205, 207],
 [306, 310, 312, 312, 314, 317, 318],
 [380, 377, 379, 382],
 [466, 469, 471, 472],
 [557, 559, 562, 566, 569]]

当然,如果有组内部差异大不相同,则会出现这种情况,如[1、4、2、5、1042、1230、920、3、2、5]。如果是这种情况,您可以尝试数字的相对差,例如,用最大(x,y)/最小(x,y)代替abs(x-y)。

 类似资料:
  • 问题内容: 带有以下数据 我想产生以下输出: 如果我按价格分组并显示最大日期和最小日期,那么我将得到以下不是我想要的内容(请参见重叠的日期)。 因此,基本上我想做的是根据组列产品和价格对数据进行逐步更改。 什么是最干净的方法来做到这一点? 问题答案: 有一种(或多或少)解决此类问题的已知技术,涉及两个调用,如下所示: 输出:

  • 问题内容: 我有一个多维数组,正在尝试根据特定列中的值将它们分组。 我正在尝试按分组,但实际上我不会事先知道该等级。因此,并不是像我可以将其放在循环中然后说那样,因为我不知道这是级别键的最大值,并且坦率地说,即使我我不确定这也不是我需要这样做的方式。做了… 我希望产生的是: 问题答案: 你需要将它们按 级别 第一 使用 foreach 循环进入数组,检查级别是否与上一个项目相同,然后将其与该数组分

  • 问题内容: 我有一个由数组组成的数组。我想通过子数组的属性对父数组进行排序。这是一个例子 我想通过在子数组中升序对父数组进行排序,因此在这种情况下,结果将是子数组颠倒(,)。使用众多的PHP排序函数中的任何一种,是否可能? 问题答案: 您可以将usort函数用作:

  • 问题是: 你有N (N代表你拥有的数字的数量)个数字。将他们分成两组,使各组数字之和的差异最小。 例子: 如果我们把1、9和3放在A组,把5和8放在B组,差异是0。 我认为首先我应该计算所有数字的总和并将其除以2。然后检查任何可能的数字组合,其总和不大于所有数字之和的一半。完成此操作后,我将选择最大的数字并打印出组。 我对所有的组合都有问题,特别是当N是大数字时。如何运行所有组合? 我的想法也有点

  • 有人知道一种方法(如果可能的话也可以使用lodash)通过对象键对对象数组进行分组,然后根据分组创建新的对象数组吗?例如,我有一个汽车对象数组: 我想制作一个由分组的新汽车对象数组:

  • 问题内容: 我有一张表格,其中存储了发生的消息。通常有一个消息“ A”,有时A被单个消息“ B”分隔。现在,我想对这些值进行分组,以便能够对它们进行分析,例如找到最长的“ A”条纹或“ A”条纹的分布。 我已经尝试了COUNT-OVER查询,但仍在为每条消息计数。 这是我的示例数据: 我想要以下输出 问题答案: 那很有趣:) 这是结果集: 该查询可能更短,但我以这种方式发布,因此您可以看到正在发生