gpt4 book ai didi

python - 对数据点进行计数/分组 : for-loop or list comprehension?

转载 作者:行者123 更新时间:2023-11-30 22:46:35 26 4
gpt4 key购买 nike

我正在尝试计算 1000 个组内的整数数据点的数量。

假设我们有 10,000 个数据点,范围为 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 个组内的数据点计数的列表的“更好”方法?

“更好”可能意味着以下之一(请详细说明):

  • 更好的性能
  • 更多Python风格
  • 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

变体 2:

# 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 做得更好! :-)

最佳答案

如果你想计算东西,最 Pythonic 的答案是 Counter,一种专门用于计数的 dict 类型。

from collections import Counter

Counter(n // 1000 for n in numbers)

结果如下:

Counter({0: 87,
1: 113,
2: 117,
3: 99,
4: 114,
...

其中键是每个“带”或组中的千人数。因此键 0 记录值 0-999,1 记录值 1000-1999,依此类推。

但是您也可以更巧妙地完成此操作。首先定义一个将值映射到带名称的函数(在本例中为单行 lambda 函数)。然后在通用生成器表达式中构造一个 Counter:

bandof = lambda x, b=1000: '{}-{}'.format(x//b*b, (x//b+1)*b-1)
Counter(bandof(n) for n in numbers)

这会产生类似的结果:

Counter({'0-999': 87,
'1000-1999': 113,
'10000-10999': 102,
'11000-11999': 114,
'12000-12999': 113,
...

键的排序不同,键更具象征意义,直接说明它们代表的范围,而不是让你在头脑中将索引转换为值范围。

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

Counter(bandof(n, 2000) for n in numbers)

产量:

Counter({'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)

您可以像以前一样调用此分类器函数。让我们疯狂一下,用不寻常的带尺寸来做:

Counter(bandtuple(n, 3924) for n in numbers)

这会产生类似的结果:

Counter({(0, 3923): 411,
(3924, 7847): 386,
(7848, 11771): 403,
(11772, 15695): 417,
(15696, 19619): 396,
...

现在,带的起始值和终止值仍然清晰,但它们也可以立即用作数据。

注意:此处给出的区间起始值和终止值是包含区间/闭区间。这对于很多用途来说都非常有用,但与 Python 的 range() 函数/生成器通常返回的半开范围有细微但关键的不同。

关于python - 对数据点进行计数/分组 : for-loop or list comprehension?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40835617/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com