python 中的分箱可变长度列表

Binning variable length lists in python

我有一个字典 d 有 100 个键,其中的值是可变长度列表,例如

 In[165]: d.values()[0]
 Out[165]: 
 [0.0432,
  0.0336,
  0.0345,
  0.044,
  0.0394,
  0.0555]

 In[166]: d.values()[1]
 Out[166]: 
 [0.0236,
  0.0333,
  0.0571]

我想做的是:对于 d.values() 中的每个列表,我想将值组织到 10 个容器中(如果满足条件,值就会被扔进容器中,例如介于 0.03 和 0.04、0.04 和 0.05 之间,等等)。

我希望最终得到的是看起来与 d 完全一样的东西,但我希望它不是 d.values()[0] 作为数字列表,而是一个列表列表,如下所示:

 In[167]: d.values()[0]
 Out[167]:
 [[0.0336,0.0345,0.0394],
  [0.0432,0.044],
  [0.0555]]

每个键仍然与相同的值相关联,但它们将被组织到 10 个容器中。

我一直对嵌套 for 循环和 if/elses 等着迷。解决这个问题的最佳方法是什么?

编辑:大家好。只是想让你知道我解决了我的问题。我使用了@Brent Washburne 答案的变体。感谢您的帮助!

您可以通过传递适当的键函数来使用 itertools.groupby() 函数来对您的项目进行分类。在这种情况下,您可以使用 floor(x*100) 作为您的关键函数:

>>> from math import floor
>>> from itertools import groupby
>>> lst = [0.0432, 0.0336, 0.0345, 0.044, 0.0394, 0.0555]
>>> [list(g) for _,g in groupby(sorted(lst), key=lambda x: floor(x*100))]
[[0.0336, 0.0345, 0.0394], [0.0432, 0.044], [0.0555]]

为了将此应用于您的价值观,您可以使用字典理解:

def categorizer(val):
    return [list(g) for _,g in groupby(sorted(lst), key=lambda x: floor(x*100))]

new_dict = {k:categorizer(v) for k,v in old_dict.items()}

作为另一种在执行速度方面更优化的方法,您可以使用字典进行分类:

>>> def categorizer(val, d={}):
...     for i in val:
...         d.setdefault(floor(i*100),[]).append(i)
...     return d.values()

为什么不将值设为一组字典,其中 ke 是 bin 指示符,而 values 是该 bin 中那些项目的列表?

yoe 会定义

newd = [{bin1:[], bin2:[], ...binn:[]}, ... ]
newd[0][bin1] = (list of items in d[0] that belong in bin1)

您现在有一个词典列表,每个词典都有相应的 bin 列表。

newd[0] 现在等同于从 d[0] 构建的字典,每个键(我称之为 bin1、bin2、... binn)包含适合该值的列表垃圾桶。因此我们有`newd[0][bin1], newd[0][bin2, ... new[k][lastbin]

字典创建允许您在进行过程中创建适当的键和值列表。如果还没有特定的 bin 键,则创建空列表,然后将值追加到列表中将成功。

现在,当您想要识别一个 bin 的元素时,您可以遍历 newd 列表并提取您想要的任何一个 bin。这允许您拥有没有条目的箱子,而不必创建空列表。如果 bin 键不在 newd 中,则检索设置为 return 默认为空列表(以避免字典无效键异常)。

def bin(values):
    bins = [[] for _ in range(10)]    # create ten bins
    for n in values:
        b = int(n * 100)              # normalize the value to the bin number
        bins[b].append(n)             # add the number to the bin
    return bins

d =  [0.0432,
  0.0336,
  0.0345,
  0.044,
  0.0394,
  0.0555]
print bin(d)

结果是:

[[], [], [], [0.0336, 0.0345, 0.0394], [0.0432, 0.044], [0.0555], [], [], [], []]