Python - 从(扩展)字典中选择第k个值的最有效方法

时间:2017-03-04 18:12:54

标签: python python-3.x dictionary percentile

我正在对数百GB的数据进行大规模分析,但它是流式的,我想要最有效的解决方案来计算模式和百分位数。我现在如何做到这一点是将数字(以小数点为单位的ping时间,如55.4381或33.97818)四舍五入到最接近的十分之一位置,并在字典中记录这些出现次数。例如:

a = {48.8: 5, 42.3: 24, 56.1: 3}

我发现这是满足我需求的最佳方式,同时仍然保持内存效率。我想到的最佳方法是使用有序字典,计算字典中的键数,并按排序顺序获取第k个键。因此,如果有意义的话,获得上述数据的第50个百分位将为a[(32*0.5)-1] -> a[15] -> 42.3。基本上抓住列表的第k个元素,如果所说的列表是[42.3, 42.3, ..., 42.3, 48.8, 48.8, 48.8, 48.8, 48.8, 56.1, 56.1, 56.1],但不需要为该列表分配内存。

所以,我想知道是否有人对最有效的方法有任何想法。我目前正在使用Python 3.5.2。谢谢你的阅读。

1 个答案:

答案 0 :(得分:0)

# We want this percentile.
pct = 0.25

# Data.
a = {48.8: 5, 42.3: 24, 56.1: 3}

# Find that percentile in this data.
def pctile(a, pct):
    # Convert to list of tuples, sort
    LofT = list(a.items())
    LofT.sort()

    # Sum of counts.
    ct = sum(a.values())

    # Index corresponding to percentile. Don't subtract 1; e.g. ct = 100,
    # 25th pctile, 25% are below, we want index 25, below which there are
    # 25 values. But do round to nearest integer.
    pcti = int(ct * pct + 0.5)

    # Traverse sorted list until this index is reached.
    for v, c in LofT:
        pcti -= c
        if pcti < 0:
            return v

    # Still here? Then pct was >= 1, just return the maximum value.
    return LofT[-1][0]

由于排序步骤,时间复杂度为O( n log n ),其中 n = len(a)