【问题标题】:Finding how many elements from a list you need to reach a certain percentage coverage从列表中查找需要多少元素才能达到一定的覆盖率
【发布时间】:2017-09-21 17:49:56
【问题描述】:

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

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

【问题讨论】:

  • 您想用最少个不同元素覆盖列表中的50%吗?
  • @JoeIddon 是的,这就是我想要的,或者任何百分比

标签: python list counter


【解决方案1】:

我会遍历most_common 并累积项目,直到达到列表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

【讨论】:

    【解决方案2】:

    如果我的列表有几十万个元素

    您可以编写一个生成器函数,该函数产生 个项目,直到超过计数百分比。生成器函数只响应迭代,它们从不将结果收集到内存中,因此无论数据大小如何,函数的内存占用都是最小的:

    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
    

    【讨论】:

    • 善用发电机 :) +1
    【解决方案3】:

    如果您愿意使用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
    

    【讨论】:

      猜你喜欢
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多