【发布时间】:2018-09-09 06:56:47
【问题描述】:
所以基本上我想计算一个浮点出现在给定列表中的次数。例如:由用户输入成绩列表(总分100分),并以十个为一组进行排序。 0-10、10-20、20-30 等)的分数出现了多少次?比如考试成绩分布。我知道我可以使用 count 功能,但由于我不是在寻找特定的数字,所以我遇到了麻烦。有没有办法结合计数和范围?感谢您的帮助。
【问题讨论】:
标签: python list count range histogram
所以基本上我想计算一个浮点出现在给定列表中的次数。例如:由用户输入成绩列表(总分100分),并以十个为一组进行排序。 0-10、10-20、20-30 等)的分数出现了多少次?比如考试成绩分布。我知道我可以使用 count 功能,但由于我不是在寻找特定的数字,所以我遇到了麻烦。有没有办法结合计数和范围?感谢您的帮助。
【问题讨论】:
标签: python list count range histogram
decs = [int(x/10) for x in scores]
从 0-9 -> 0、10-19 -> 1 等范围内映射分数。然后只计算 0、1、2、3 等的出现次数(通过 collections.Counter 之类的东西),并从那里映射回范围。
【讨论】:
x//10 将生成 float 结果,而 int(x/10) 将生成 int。
list.count 的事情,所以我不知道你为什么提到这个。
// 非常棒,所以我会随时提出来。
此方法使用二分法,效率更高,但需要您先对分数进行排序。
from bisect import bisect
import random
scores = [random.randint(0,100) for _ in xrange(100)]
bins = [20, 40, 60, 80, 100]
scores.sort()
counts = []
last = 0
for range_max in bins:
i = bisect(scores, range_max, last)
counts.append(i - last)
last = i
我不希望您为此安装 numpy,但如果您已经拥有 numpy,则可以使用 numpy.histogram。
更新
首先,使用 bisect 更加灵活。使用 [i//n for i in scores] 要求所有 bin 的大小相同。使用 bisect 允许 bin 具有任意限制。 i//n 也表示范围是 [lo, hi)。使用 bisect 范围是 (lo, hi] 但如果你想要 [lo, hi) 可以使用 bisect_left。
第二个平分速度更快,请参阅下面的时间安排。我已经用较慢的 sorted(scores) 替换了 scores.sort() 因为排序是最慢的步骤,我不想用预先排序的数组来偏差时间,但是 OP 说他/她的数组已经在这种情况下,对分进行排序可能更有意义。
setup="""
from bisect import bisect_left
import random
from collections import Counter
def histogram(iterable, low, high, bins):
step = (high - low) / bins
dist = Counter(((x - low + 0.) // step for x in iterable))
return [dist[b] for b in xrange(bins)]
def histogram_bisect(scores, groups):
scores = sorted(scores)
counts = []
last = 0
for range_max in groups:
i = bisect_left(scores, range_max, last)
counts.append(i - last)
last = i
return counts
def histogram_simple(scores, bin_size):
scores = [i//bin_size for i in scores]
return [scores.count(i) for i in range(max(scores)+1)]
scores = [random.randint(0,100) for _ in xrange(100)]
bins = range(10, 101, 10)
"""
from timeit import repeat
t = repeat('C = histogram(scores, 0, 100, 10)', setup=setup, number=10000)
print min(t)
#.95
t = repeat('C = histogram_bisect(scores, bins)', setup=setup, number=10000)
print min(t)
#.22
t = repeat('histogram_simple(scores, 10)', setup=setup, number=10000)
print min(t)
#.36
【讨论】:
bisect 的不同用法,而不是您在这里最终所做的(即,使用 bisect 来查找单个分数进入哪个 bin,会是一种浪费)。对于大量的分数,你是对的,二分法可能是有效的。
要对数据进行分组,请将其除以间隔宽度。要计算每组中的数量,请考虑使用collections.Counter。这是一个带有文档和测试的示例:
from collections import Counter
def histogram(iterable, low, high, bins):
'''Count elements from the iterable into evenly spaced bins
>>> scores = [82, 85, 90, 91, 70, 87, 45]
>>> histogram(scores, 0, 100, 10)
[0, 0, 0, 0, 1, 0, 0, 1, 3, 2]
'''
step = (high - low + 0.0) / bins
dist = Counter((float(x) - low) // step for x in iterable)
return [dist[b] for b in range(bins)]
if __name__ == '__main__':
import doctest
print doctest.testmod()
【讨论】:
[float(i) for i in examScores] 之类的操作。
如果你对使用外部库 NumPy 没问题,那么你只需要调用numpy.histogram():
>>> data = [82, 85, 90, 91, 70, 87, 45]
>>> counts, bins = numpy.histogram(data, bins=10, range=(0, 100))
>>> counts
array([0, 0, 0, 0, 1, 0, 0, 1, 3, 2])
>>> bins
array([ 0., 10., 20., 30., 40., 50., 60., 70., 80.,
90., 100.])
【讨论】: