我想要统计给定列表中浮点数出现的次数。比如,用户输入了一组成绩(都是100分制),并按照十分为一组进行排序。每一组中0-10分、10-20分、20-30分等得分段各出现了多少次?就像测试成绩分布一样。我知道可以使用 count 函数,但由于我不是在寻找特定的数字,所以我遇到了麻烦。有没有办法将 count 和 range 结合起来呢?感谢任何帮助。
将数据进行分组,通过间隔宽度进行划分。要计算每个组中的数量,请考虑使用 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()
如果您愿意使用外部库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.])
decs = [int(x/10) for x in scores]
将得分从0-9映射为0,10-19映射为1,以此类推。然后通过类似于collections.Counter
的方式计算0、1、2、3等出现的次数,并从那里映射回范围。
x//10
会生成一个 float
结果,而 int(x/10)
会生成一个 int
。 - Amberlist.count
,所以我不确定你为什么要提到它。 - Amber//
很棒,所以我会在任何时候提起它。 - Bi Rico这种方法使用二分查找,可以更高效,但需要先对分数进行排序。
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
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找到个人分数所属的箱子,这将是浪费)。对于大量的分数,你是正确的,bisect可能是高效的。 - Amber
[float(i) for i in examScores]
。 - Bi Rico