【问题标题】:Divide a list into multiple lists based on a bin size根据 bin 大小将列表划分为多个列表
【发布时间】:2012-07-01 12:41:02
【问题描述】:

我有一个包含超过 100,000 个值的列表。

我需要根据特定的 bin 宽度(例如 0.1)将列表分成多个较小的列表。谁能帮我写一个python程序来做到这一点?

我的列表是这样的

-0.234
-0.04325
-0.43134
-0.315
-0.6322
-0.245
-0.5325
-0.6341
-0.5214
-0.531
-0.124
-0.0252

我想要这样的输出

list1 = [-0.04325, -0.0252] 
list2 = [-0.124] 
list3 = [-0.234, -0.245 ] 
list4 = [-0.315] 
list5 = [-0.43134] 
list6 = [-0.5325, -0.5214, -0.531] 
list7 = [-0.6322, -0.6341]

【问题讨论】:

  • 您提供了示例输入;还请提供预期的输出。

标签: python


【解决方案1】:

这是一个使用numpys digitize的简单而好方法:

>>> import numpy as np
>>> mylist = np.array([-0.234, -0.04325, -0.43134, -0.315, -0.6322, -0.245,
                       -0.5325, -0.6341, -0.5214, -0.531, -0.124, -0.0252])
>>> bins = np.arange(0,-1,-0.1)
>>> for i in xrange(1,10):
...     mylist[np.digitize(mylist,bins)==i]
... 
array([-0.04325, -0.0252 ])
array([-0.124])
array([-0.234, -0.245])
array([-0.315])
array([-0.43134])
array([-0.5325, -0.5214, -0.531 ])
array([-0.6322, -0.6341])
array([], dtype=float64)
array([], dtype=float64)

digitize,返回一个数组,其中包含每个元素所在的 bin 的索引值。

【讨论】:

    【解决方案2】:

    这将创建一个 dict,其中每个值都是适合 bin 的元素列表。

    import collections
    bins = collections.defaultdict(list)
    binId = lambda x: int(x*10)
    for val in vals:
        bins[binId(val)].append(val)
    

    【讨论】:

    • 你能告诉我第 3 行发生了什么吗?
    • @user 它正在创建一个 lambda。这是一个将值映射到 bin id 的临时函数。如果您想要更深入的信息,我建议您搜索“python lambda”。
    【解决方案3】:

    这是你想要的吗? (示例输出会很有帮助:)

    f = [-0.234, -0.04325, -0.43134, -0.315, -0.6322, -0.245, 
         -0.5325, -0.6341, -0.5214, -0.531, -0.124, -0.0252]
    
    import numpy as np
    data = np.array(f)
    hist, edges = np.histogram(data, bins=10)
    print hist
    

    产量:

     [2 3 0 1 0 1 2 0 1 2]
    

    这个 SO 问题assigning points to bins 可能会有所帮助。

    【讨论】:

    • 直方图给出了一个 bin 中的元素数量,而不是元素本身。我试过了。我在原始问题中包含了一个示例输出。
    • @user1492449 感谢您的反馈,我会仔细考虑并发布另一个答案。同时编辑您的帖子以使输出更具可读性。
    【解决方案4】:

    这行得通:

    l=[-0.234, -0.04325, -0.43134, -0.315, -0.6322, -0.245,
    -0.5325, -0.6341, -0.5214, -0.531, -0.124, -0.0252]
    
    d={}
    for k,v in zip([int(i*10) for i in l],l):
       d.setdefault(k,[]).append(v)
    
    LoL=[d[e] for e in sorted(d.keys(), reverse=True)]
    
    for i,l in enumerate(LoL,1):
        print('list',i,l)    
    

    打印:

    list 1 [-0.04325, -0.0252]
    list 2 [-0.124]
    list 3 [-0.234, -0.245]
    list 4 [-0.315]
    list 5 [-0.43134]
    list 6 [-0.5325, -0.5214, -0.531]
    list 7 [-0.6322, -0.6341]
    

    它是如何工作的:

    1: The list
    >>> l=[-0.234, -0.04325, -0.43134, -0.315, -0.6322, -0.245,
    ... -0.5325, -0.6341, -0.5214, -0.531, -0.124, -0.0252]
    
    2: Produce the keys:
    >>> [int(i*10) for i in l]
    [-2, 0, -4, -3, -6, -2, -5, -6, -5, -5, -1, 0]
    
    3: Produce tuples to put in the dict:
    >>> zip([int(i*10) for i in l],l)
    [(-2, -0.234), (0, -0.04325), (-4, -0.43134), (-3, -0.315), (-6, -0.6322), 
     (-2, -0.245), (-5, -0.5325), (-6, -0.6341), (-5, -0.5214), (-5, -0.531), 
     (-1, -0.124), (0, -0.0252)]
    
    4: unpack the tuples into k,v and loop over the list
    >>>for k,v in zip([int(i*10) for i in l],l):
    
    5: add k key to a dict (if not there) and append the float value to a list associated 
       with that key:
        d.setdefault(k,[]).append(v)
    

    我建议就这些语句编写 Python 教程。

    【讨论】:

    • 感谢您的回复,它有效。你能解释一下吗?
    【解决方案5】:

    分箱可以通过itertools.groupby:

    import itertools as it
    
    
    iterable = ['-0.234', '-0.04325', '-0.43134', '-0.315', '-0.6322', '-0.245',
                '-0.5325', '-0.6341', '-0.5214', '-0.531', '-0.124', '-0.0252']
    
    a,b,c,d,e,f,g = [list(g) for k, g in it.groupby(sorted(iterable), key=lambda x: x[:4])]
    c
    # ['-0.234', '-0.245']
    

    注意:这个简单的 key 函数假设 iterable 中的值在 -0.0 和 -10.0 之间。对于一般情况,请考虑 lambda x: "{:.1f}".format(float(x))

    有关groupby 工作原理的详细信息,另请参阅post

    【讨论】:

      【解决方案6】:

      我们可以使用第三方库more_itertools制作bin。

      给定

      iterable = (
          "-0.234 -0.04325 -0.43134 -0.315 -0.6322 -0.245 "
          "-0.5325 -0.6341 -0.5214 -0.531 -0.124 -0.0252"
      ).split()
      
      iterable
      # ['-0.234', '-0.04325', '-0.43134', '-0.315', '-0.6322', '-0.245', '-0.5325', '-0.6341', '-0.5214', '-0.531', '-0.124', '-0.0252']
      

      代码

      import more_itertools as mit
      
      
      keyfunc = lambda x: float("{:.1f}".format(float(x)))
      bins = mit.bucket(iterable, key=keyfunc)
      
      keys = [-0.0,-0.1,-0.2, -0.3,-0.4,-0.5,-0.6]
      a,b,c,d,e,f,g = [list(bins[k]) for k in keys]
      c
      # ['-0.234', '-0.245']
      

      详情

      我们可以通过 key 函数进行 bin,我们定义它来将数字格式化为单精度,即 -0.213-0.2

      keyfunc = lambda x: float("{:.1f}".format(float(x)))
      bins = mit.bucket(iterable, key=keyfunc)
      

      这些 bin 由 key 函数定义的键访问:

      c = list(bins[-0.2])
      c
      # ['-0.234', '-0.245']
      

      通过迭代键访问所有 bin:

      f = lambda x: float("{:.1f}".format(float(x)))
      bins = mit.bucket(iterable, key=keyfunc)
      
      keys = [-0.0,-0.1,-0.2, -0.3,-0.4,-0.5,-0.6]
      for k in keys:
          print("{} --> {}".format(k, list(bins[k])))
      

      输出

      -0.0 --> ['-0.04325', '-0.0252']
      -0.1 --> ['-0.124']
      -0.2 --> ['-0.234', '-0.245']
      -0.3 --> ['-0.315']
      -0.4 --> ['-0.43134']
      -0.5 --> ['-0.5325', '-0.5214', '-0.531']
      -0.6 --> ['-0.6322', '-0.6341']
      

      列表理解和解包是另一种选择(参见代码示例)。

      有关详细信息,另请参阅more_itertools docs

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-02
        • 1970-01-01
        • 1970-01-01
        • 2011-08-15
        • 1970-01-01
        • 2022-12-22
        • 2016-11-25
        相关资源
        最近更新 更多