代码之家  ›  专栏  ›  技术社区  ›  sberry

python:根据特定范围内的项目数从列表中创建分发

  •  1
  • sberry  · 技术社区  · 14 年前

    我将此问题标记为 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]
    < /代码> 
    
    

    因为我有3个项目,范围是0-9、10-19、30-39和50-59。使用这个结果,我可以生成一个图像,在我的最终发行版中分割出部分(深色)。下面可以看到我正在尝试创建的图像类型的一个示例,它将使用更多的数据生成。暂时忽略蓝线。

    我知道如何做到这一点,通过迭代列表中的每个项目并像这样进行计算的方法。但是,我的数据集可能有几十万甚至数百万个数字。在现实世界中,我的范围(10)和所需项目数(3)可能要大得多。

    谢谢你的帮助。

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

    例如:

    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]
    

    因为我有3个项目,范围是0-9、10-19、30-39和50-59。使用这个结果,我可以生成一个图像,在我的最终发行版中分割出部分(深色)。下面可以看到我正在尝试创建的图像类型的一个示例,它将使用更多的数据生成。暂时忽略蓝线。

    我知道怎么做蛮力迭代列表中的每一项并进行类似计算的方法。但是,我的数据集可能有几十万甚至数百万个数字。我的范围(10)和所需的项目数(3)在现实世界中可能要大得多。

    distribution image

    谢谢你的帮助。

    3 回复  |  直到 14 年前
        1
  •  4
  •   Alex Martelli    14 年前

    如果 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]
    

    如果 数据 未排序,或者如果不知道,请使用 sorted(data) 作为第一个论点 itertools.groupby 而不是仅仅 数据 .

    如果您喜欢不那么密集/紧凑的方法,当然可以将其扩展,例如:

    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中作为其第一个参数的每个项,以获取每个项的“key”;对于具有相同“key”的每个连续项组, 子句 生成一个包含两个项的元组:键的值,以及一个对所述组中所有项都可iterable。

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

        2
  •  2
  •   unutbu    14 年前

    自从 data 可能会很长,您可能希望研究使用 numpy . 它为数值计算提供了许多有用的功能,它需要较少的内存来存储 数据 在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]
    

    [*]--注意:在上面的代码中,在定义过程中形成了一个python列表。 数据 . 所以这里的最大内存需求实际上比刚才使用的python列表要大。但是,如果没有其他对python列表的引用,那么内存应该被释放。或者,如果数据存储在磁盘上, numpy.loadtxt 可用于将其直接读取到numpy数组中。

        3
  •  0
  •   Community CDub    7 年前

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