Python 计数/分组数据点:用于循环或列表理解?

Python 计数/分组数据点:用于循环或列表理解?,python,list,list-comprehension,Python,List,List Comprehension,我试图计算1000个组中的整数数据点 假设我们有10000个数据点,范围为0..999999: import random random.seed(123456) # generate a reproducable sequence # make 10000 numbers in range 0..99999 maxn = 99999 numbers = [random.randint(0,maxn) for i in range(10000)] 现在,哪种变体是生成一个列表的“更好”方法,

我试图计算1000个组中的整数数据点

假设我们有10000个数据点,范围为0..999999:

import random
random.seed(123456) # generate a reproducable sequence

# make 10000 numbers in range 0..99999
maxn = 99999
numbers = [random.randint(0,maxn) for i in range(10000)]
现在,哪种变体是生成一个列表的“更好”方法,该列表包含每个1000组中已计数的数据点数量

“更好”可指以下情况之一(请详细说明):

  • 更好的性能
  • 更像蟒蛇
  • 6个月后可读性更好
变体1:

# generate a zero-initialized "array" to hold the counts per 1000's block
blocks1 = [0 for i in range(maxn/1000 +1)] # init 1D "array"

for num in numbers:
    blocks1[num / 1000] += 1 # int divide by 1000 gives index

print blocks1[1] # show how many in range 1000..1999
# Use a really wild list comprehension:
blocks2 = [len(filter(lambda num: num/1000 == i, numbers))
    for i in range(maxn/1000+1)]

print blocks2[1] # show how many in range 1000..1999
变体2:

# generate a zero-initialized "array" to hold the counts per 1000's block
blocks1 = [0 for i in range(maxn/1000 +1)] # init 1D "array"

for num in numbers:
    blocks1[num / 1000] += 1 # int divide by 1000 gives index

print blocks1[1] # show how many in range 1000..1999
# Use a really wild list comprehension:
blocks2 = [len(filter(lambda num: num/1000 == i, numbers))
    for i in range(maxn/1000+1)]

print blocks2[1] # show how many in range 1000..1999

感谢您帮助我在Python中做得更好!:-)

如果你想数数东西,最好的答案是一个
计数器
,一种专门用于计数的
dict

从集合导入计数器
计数器(n//1000表示n个数字)
结果如下:

计数器({0:87,
1: 113,
2: 117,
3: 99,
4: 114,
...
其中键是每个“带”或组中的千位数。因此键0记录值0-999,1000-1999中的1,依此类推

但您也可以更灵活地执行此操作。首先定义一个函数(在本例中为一行lambda函数),该函数将值映射到带名称中。然后跨通用生成器表达式构造一个
计数器

bandof=lambda x,b=1000:'{}-{}'。格式(x//b*b,(x//b+1)*b-1)
计数器(n个数字中n个的带宽)
这会产生如下结果:

计数器({'0-999':87,
'1000-1999': 113,
'10000-10999': 102,
'11000-11999': 114,
'12000-12999': 113,
...
键的顺序不同,键更具符号性,直接说明它们所代表的范围,而不是让你将索引转换为你头脑中的值范围

这样概括的一个好处是,任何时候您想要更改频带大小,这都是微不足道的。例如,对于频带大小2000:

计数器(n个数字的频带宽度(n,2000)
收益率:

计数器({'0-1999':200,
'10000-11999': 216,
'12000-13999': 235,
'14000-15999': 186,
'16000-17999': 188,
...
选择100号、250号、500号、1000号、5000号或任何你喜欢的号码。它也不局限于漂亮的整数。如果你想要391号的号码,也可以

最后一个诀窍是:虽然字符串键对于打印目的很有吸引力,但它们对于排序和其他类型的进一步处理可能不太方便。因此,与其将组名格式化为字符串,不如使用
元组

bandtuple=lambda x,b=1000:(x//b*b,(x//b+1)*b-1)
您可以像以前一样调用此分类程序函数。让我们疯狂地使用不寻常的条带大小:

计数器(n个数字的带元组(n,3924))
这会产生如下结果:

计数器({(03923):411,
(3924, 7847): 386,
(7848, 11771): 403,
(11772, 15695): 417,
(15696, 19619): 396,
...
现在波段开始和停止值仍然清晰,但它们也可以立即用作数据


注意:这里给出的带区开始和停止值是包含/闭合的间隔。这在很多情况下都非常有用,但与Python的
范围()通常返回的半开放范围略有不同
函数/生成器。

非常感谢
集合
计数器
的提示。我想这是一个非常值得检查的模块。我想我会按照您建议的路线使用
计数器
并让它返回元组/值对。感谢您的时间和精彩的解释!回答已接受:-)