我用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)可能会大得多。
感谢您的帮助。
答案 0 :(得分: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=
传递的可调用数应用于作为其第一个参数传递的iterable中的每个项,以获得每个项的“键”;对于具有相同“键”的每个连续项目组,groupby
产生一个包含两个项目的元组:键的值,以及所述组中所有项目的可迭代项。
这里,通过将项目除以10(截断)获得密钥; len(list(g))
是具有该“密钥”的连续项目的数量。由于这些项目必须是连续的,因此您需要对数据进行排序(并且,对它进行排序更简单,而不是“按值除以10并对其进行排序”; - )。
答案 1 :(得分:2)
由于data
可能非常冗长,您可能需要考虑使用numpy。它为数值工作提供了许多有用的函数,它需要更少的内存来存储{n}数组中的data
而不是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列表时的内存需求。但是,如果没有对Python列表的其他引用,则应释放内存。或者,如果数据存储在磁盘上,则可以使用numpy.loadtxt
将其直接读取到numpy数组中。
答案 2 :(得分:0)
这听起来像某种形式的直方图。为了实现这一目标,不需要预先分类。我讨论了使用存储桶排序的变体来对附近的元素here进行分组,但您需要调整此算法以适合您的目的。请注意,您不需要将数字本身存储在存储桶中以形成直方图