我有一长串x = [4,6,7,8,8,8,9,0,9,1,7,7] 我知道我可以使用计数器来查看项目出现的次数。
x = [4,6,7,8,8,8,9,0,9,1,7,7]
from collections import Counter
Counter(x)
>>Counter({0: 1, 1: 1, 4: 1, 6: 1, 7: 3, 8: 3, 9: 2})
我可以使用以下方式对它们进行排序:
Counter(x).most_common()
>>Counter(x).most_common()
Out[33]: [(7, 3), (8, 3), (9, 2), (0, 1), (1, 1), (4, 1), (6, 1)]
现在,我想知道我需要多少元素才能覆盖50%的列表。例如,7和8出现6次,有12个元素,所以我只需要7和8来覆盖列表中50%的元素。如果我添加9,我有8个元素,所以7,8和9覆盖了列表中66%的元素。
如果我的列表中有数十万个元素,我该怎么做?
答案 0 :(得分:3)
我只是迭代len
并累积这些项目,直到达到列表def common_elements(lst, pct):
required = len(lst) * pct
found = 0
result = []
for tup in Counter(lst).most_common():
result.append(tup[0])
found += tup[1]
if found >= required:
break
return result
的给定百分比:
{{1}}
答案 1 :(得分:3)
如果我的列表有数十万个元素
您可以编写产生项目的生成器函数,直到超过计数百分比。生成器函数只响应迭代,它们从不在内存中收集结果,因此无论数据大小如何,函数的内存占用都是最小的:
def func(lst, percentage=0.5):
cnt = 0
for x, y in Counter(lst).most_common():
cnt += y
if cnt > len(lst)*percentage:
return
yield x
for p in func(x):
print(p)
# 7
# 8
答案 2 :(得分:2)
如果您愿意使用numpy
,则不需要循环,并使用分箱,排序和计数等概念来计算结果:
thresh = 0.5
vals, counts = np.unique(x, return_counts=True)
idx = counts.argsort()
vals = vals[idx][::-1]
w = np.where(np.cumsum(counts[idx][::-1]/len(x)) > thresh)[0][0]
print(vals[range(w)])
# for x = [4,6,7,8,8,8,9,0,9,1,7,7]
# the result is: [8, 7]
与@Moses的性能比较
# large array
x = np.random.randint(0, 1000, 10000)
# @Moses :
timeit.timeit("moses()", setup="from __main__ import func, moses", number=1000)
Out[8]: 1.9789454049896449
# @this :
timeit.timeit("f1()", setup="from __main__ import f1", number=1000)
Out[6]: 0.5699292980134487