识别列表中相似数字的组

时间:2015-12-23 14:56:02

标签: python list

我有数据列表,我想根据相似性进行分组。列表中的数字顺序是固定的,对于保存很重要。

作为一个例子,这里是我想要实现的目标的可视化:

Black line is the list of numbers, green lines are the identified groups of similar numbers I'd like to identify, corresponding with that section of the list.

黑线表示我拥有的数字列表。绿线表示我想在此示例列表中标识的分组。

列表中的数字顺序很重要,无法更改(例如,无法按升序或降序排序)。列表中的数字不是连续的(即不可能有 if indexPath.row < facebookPics.count { if let imgData = NSData(contentsOfURL: self.facebookPics[indexPath.row]){ let image = UIImage(data: imgData) collectionCell.collectionViewImage.image = image } } 的列表,但可能类似6, 6, 6, 6)。

有没有办法做到这一点?

修改:示例值和所需的分组:

5.85, 6.1, 5.96, 5.88

会导致

的近似分组

[4.1, 4.05, 4.14, 4.01, 3.97, 4.52, 4.97, 5.02, 5.05, 5.2, 5.18, 3.66, 3.77, 3.59, 3.72]

在上面的分组中,您可以说[(4.1, 4.05, 4.14, 4.01, 3.97, 4.52), (4.97, 5.02, 5.05, 5.2, 5.18), (3.66, 3.77, 3.59, 3.72)]可能属于第一组或第二组。如果像我在上面的示例中所做的那样可视化,则分组将由绿线表示。我的列表实际上是几百到几千个值。

5 个答案:

答案 0 :(得分:4)

您可以使用itertools.groupby - 它将连续元素与给定键函数的结果相同(在这种情况下为round):

In [7]: import itertools

In [8]: data = [4.1, 4.05, 4.14, 4.01, 3.97, 4.52, 4.97, 5.02, 5.05, 5.2, 5.18, 3.66, 3.77, 3.59, 3.72]

In [9]: [tuple(xs) for _, xs in itertools.groupby(data, round)]
Out[9]: 
[(4.1, 4.05, 4.14, 4.01, 3.97),
 (4.52, 4.97, 5.02, 5.05, 5.2, 5.18),
 (3.66, 3.77, 3.59, 3.72)]

答案 1 :(得分:3)

from statistics import mean

def ordered_cluster(data, max_diff):
    current_group = ()
    for item in data:
        test_group = current_group + (item, )
        test_group_mean = mean(test_group)
        if all((abs(test_group_mean - test_item) < max_diff for test_item in test_group)):
            current_group = test_group
        else:
            yield current_group
            current_group = (item, )
    if current_group:
        yield current_group

data = [4.1, 4.05, 4.14, 4.01, 3.97, 4.52, 4.97, 5.02, 5.05, 5.2, 5.18, 3.66, 3.77, 3.59, 3.72]

print(list(ordered_cluster(data, 0.5)))

输出:

[(4.1, 4.05, 4.14, 4.01, 3.97, 4.52), (4.97, 5.02, 5.05, 5.2, 5.18), (3.66, 3.77, 3.59, 3.72)]

这可确保组中的每个项目不超过max_diff到组的平均值。如果是,则启动新组。

答案 2 :(得分:2)

您可以使用itertools.groupby根据特定差异(在这种情况下为2)对数据进行分类。

from itertools import groupby, chain
from collections import OrderedDict

def grouper(_lst, interval):
    z = zip(_lst,_lst[1:])
    return [OrderedDict.fromkeys(chain.from_iterable(g)).keys() for k,g in groupby(z,key=lambda x:x[1]-x[0]<interval) if k]

我在这里使用了OrderedDict.fromkeys来保存特定订单中的唯一商品。

演示:

test = [0, 1.3, 2.2, 2.9, 6, 7.8, 8, 9.1, 10.4,15, 16, 17.6, 17.7, 18.9]
print(grouper(test, 2))
[[0, 1.3, 2.2, 2.9], [6, 7.8, 8, 9.1, 10.4], [15, 16, 17.6, 17.7, 18.9]]

答案 3 :(得分:2)

numpy版本:

l = [4.1, 4.05, 4.14, 4.01, 3.97, 4.52, 4.97, 5.02, 5.05, 5.2, 5.18, 3.66, 3.77, 3.59, 3.72]

import numpy as np

x = np.array(l)
mask = np.diff(np.round(x))
print(np.split(x, np.where(mask)[0] + 1))
[array([ 4.1 ,  4.05,  4.14,  4.01,  3.97]), array([ 4.52,  4.97,  5.02,  5.05,  5.2 ,  5.18]), array([ 3.66,  3.77,  3.59,  3.72])]

或者:

import numpy as np

diff = .5
x = np.array(l)
mask = np.abs(x[:-1] - x[1:]) <= diff
print(np.split(x, np.where(~mask)[0] + 1)
[array([ 4.1 ,  4.05,  4.14,  4.01,  3.97]), array([ 4.52,  4.97,  5.02,  5.05,  5.2 ,  5.18]), array([ 3.66,  3.77,  3.59,  3.72])]

答案 4 :(得分:1)

<强> https://en.wikipedia.org/wiki/K-means_clustering k均值聚类是一种矢量量化方法,最初来自信号处理,是数据挖掘中聚类分析的常用方法。 k均值聚类的目的是将n个观测值划分为k个聚类,其中每个观测值属于具有最近均值的聚类,作为聚类的原型。这导致数据空间划分为Voronoi单元。