查找列表中需要达到特定百分比覆盖率的元素数量

时间:2017-09-21 17:49:56

标签: python list counter

我有一长串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%的元素。

如果我的列表中有数十万个元素,我该怎么做?

3 个答案:

答案 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