按嵌套值的频率排序嵌套字典

Ordering a nested dictionary by the frequency of the nested value

我有这个 list 由一个巨大的 csv 制成。 对于 list 中的每一项,我都将其分解为 iddetailsid 的最大长度始终在 0-3 个字符之间,而 details 是可变的。 我创建了一个空字典,D...(下面的其余代码):

D={}

for v in list:

    id = v[0:3]
    details = v[3:]

    if id not in D:
        D[id] = {}

    if details not in D[id]:
        D[id][details] = 0

    D[id][details] += 1

旁白:你能帮我理解这两个 if 语句在做什么吗? 对 python 和编程非常陌生。

无论如何,它会产生这样的东西:

{'KEY1_1': {'key2_1' : value2_1, 'key2_2' : value2_2, 'key2_3' : value2_3},
'KEY1_2': {'key2_1' : value2_1, 'key2_2' : value2_2, 'key2_3' : value2_3},
and many more KEY1's with variable numbers of key2's

每个 'KEY1' 都是独一无二的,但每个 'key2' 则不一定。 value2_ s个个都不一样

好的,现在我找到了一种按第一个 KEY 排序的方法

for k, v in sorted(D.items()):
    print k, ':', v

我已经做了足够多的研究,知道字典不能真正排序,但我不关心排序,我关心顺序或更具体的出现频率。在我的代码中,value2_x 是特定 KEY1_x 对应的 key2_x 出现的次数。我开始认为我应该使用更好的变量名。

问题:top-level/overall字典如何按嵌套字典中value2_x中的数字排序?我想对这些数字进行一些统计,例如...

  1. 最频繁的 KEY1_x:key2_x 对出现了多少次?
  2. 最常见的 KEY1_x:key2_x 10、20、30 对是什么?

我可以只做每个 KEY1 还是我可以整体做?奖励:如果我能以这种方式为 presentation/sharing 订购它,那将非常有帮助,因为它是一个如此大的数据集。非常感谢,我希望我已经明确了我的问题和意图。

您可以使用 Counter 根据频率对密钥对进行排序。它还提供了一种获取 x 个最频繁项目的简单方法:

from collections import Counter

d = {
    'KEY1': {
        'key2_1': 5,
        'key2_2': 1,
        'key2_3': 3
    },
    'KEY2': {
        'key2_1': 2,
        'key2_2': 3,
        'key2_3': 4
    }
}

c = Counter()
for k, v in d.iteritems():
    c.update({(k, k1): v1 for k1, v1 in v.iteritems()})

print c.most_common(3)

输出:

[(('KEY1', 'key2_1'), 5), (('KEY2', 'key2_3'), 4), (('KEY2', 'key2_2'), 3)]

如果您只关心最常见的键对,没有其他理由构建嵌套字典,您可以使用以下代码:

from collections import Counter

l = ['foobar', 'foofoo', 'foobar', 'barfoo']
D = Counter((v[:3], v[3:]) for v in l)
print D.most_common() # [(('foo', 'bar'), 2), (('foo', 'foo'), 1), (('bar', 'foo'), 1)]

简短说明((v[:3], v[3:]) for v in l) 是一个 generator expression,它将生成 tuples,其中第一项与您的顶级密钥相同原始 dict 和第二项与嵌套 dict.

中的键相同
>>> x = list((v[:3], v[3:]) for v in l)
>>> x
[('foo', 'bar'), ('foo', 'foo'), ('foo', 'bar'), ('bar', 'foo')]

Counterdict 的子类。它接受 iterable 作为参数,iterable 中的每个唯一元素将用作键,值是 iterable.

中元素的计数
>>> c = Counter(x)
>>> c
Counter({('foo', 'bar'): 2, ('foo', 'foo'): 1, ('bar', 'foo'): 1})

因为 generator expression is an iterable 没有必要将其转换为中间的列表,所以构造可以简单地用 Counter((v[:3], v[3:]) for v in l).

完成

您询问的 if 语句正在检查密钥是否存在于 dict:

>>> d = {1: 'foo'}
>>> 1 in d
True
>>> 2 in d
False

因此以下代码将检查字典 D 中是否存在值为 id 的键,如果不存在,它将在那里分配空字典。

if id not in D:
    D[id] = {}

第二个 if 对嵌套字典的作用完全相同。