2

我标记了这个问题,poisson因为我不确定它在这种情况下是否有帮助。

我需要从数据列表中创建一个分布(可能最终格式化为图像)。

例如:

data = [1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 10, 10, 10, 22, 30, 30, 35, 46, 58, 59, 59]

以便数据可用于创建可视分布。例如,在这种情况下,我可能会说范围在 10 中,并且每个范围中至少需要 3 个项目才能成为有效点。

有了这个示例数据,我希望结果类似于

ditribution = [1, 2, 4, 6]

因为我在 0-9、10-19、30-39 和 50-59 范围内有 > 3 个项目。使用该结果,我可以生成一个图像,该图像具有在我的最终分布中存在的部分被分割出来(较深的颜色)。我正在尝试创建的图像类型的示例如下所示,并且会使用更多数据生成。暂时忽略蓝线。

我知道如何以蛮力的方式迭代列表中的每个项目并像这样进行计算。但是,我的数据集可能有数十万甚至数百万的数字。在现实世界的示例中,我的范围 (10) 和所需的项目数 (3) 可能会大得多。

分布图

谢谢你的帮助。

4

3 回答 3

4

如果data总是排序,一个紧凑的方法可能是:

import itertools as it

d = [k+1 for k, L in
         ((k, len(list(g))) for k, g in it.groupby(data,key=lambda x:x//10))
     if L>=3]

如果data未排序,或者您不知道,请sorted(data)用作 的第一个参数itertools.groupby,而不仅仅是data.

如果您更喜欢不太密集/紧凑的方法,您当然可以扩展它,例如:

def divby10(x): return x//10

distribution = []
for k, g in it.groupby(data, key=divby10):
    L = len(list(g))
    if L < 3: continue
    distribution.append(k+1)

在任何一种情况下,机制都是groupby首先将传递的可调用对象应用于key=作为其第一个参数传递的可迭代对象中的每个项目,以获得每个项目的“键”;对于每个具有相同“键”的连续项目组,groupby产生一个包含两个项目的元组:键的值,以及对所述组中所有项目的可迭代。

这里,密钥是通过将一个项目除以 10 获得的(带截断);len(list(g))是具有该“键”的连续项目数。由于项目必须是连续的,因此您需要对数据进行排序(而且,对它进行排序比“按值除以 10 并截断”进行排序更简单;-)。

于 2010-08-23T18:18:15.600 回答
4

由于data可能很长,您可能需要考虑使用numpy。它为数值工作提供了许多有用的函数,存储data在 numpy 数组中比 Python 列表 [*] 需要更少的内存,并且由于许多 numpy 函数在后台调用 C 函数,您可能能够获得一些速度收获:

import numpy as np

data = np.array([1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 10, 10, 10, 22, 30, 30, 35, 46, 58, 59, 59])

hist,bins=np.histogram(data,bins=np.linspace(0,60,7))
print(hist)
# [11  3  1  3  1  3]

distribution=np.where(hist>=3)[0]+1
print(distribution)
# [1 2 4 6]

[*] -- 注意:在上面的代码中,在定义data. 因此,这里的最大内存需求实际上比您刚刚使用 Python 列表时要大。但是,如果没有其他对 Python 列表的引用,则应该释放内存。或者,如果数据存储在磁盘上,numpy.loadtxt可用于将其直接读取到 numpy 数组中。

于 2010-08-23T20:23:02.523 回答
0

这听起来像是某种形式的直方图的工作。为了实现这一点,不需要进行预分类。我在这里讨论了使用桶排序的变体对附近的元素进行分组,尽管您需要调整此算法以适合您的目的。请注意,您不需要将数字本身存储在桶中以形成直方图

于 2010-08-23T18:35:08.037 回答