在python中使用带嵌套字典的计数器

时间:2017-09-15 06:39:58

标签: python

我在python中有一个dicts列表,如下所示:

midd()

如何获得列表的每个字典中的键的总和,以便我有:

[
  {
    "25-34": {
      "Clicks": 10
    },
    "45-54": {
      "Clicks": 2
    },

  },
  {
    "25-34": {
      "Clicks": 20
    },
    "45-54": {
      "Clicks": 10
    },

  }   
]

我尝试使用{ "25-34": { "Clicks": 30 }, "45-54": { "Clicks": 12 }, } ,但是当Counter()内部列表是平的时,它很容易,但是如上所述嵌套的dicts会出现此错误:

dicts

如何实现如上所述的求和。

注意:我已添加 /usr/lib/python2.7/collections.pyc in update(self, iterable, **kwds) 524 self_get = self.get 525 for elem, count in iterable.iteritems(): --> 526 self[elem] = self_get(elem, 0) + count 527 else: 528 super(Counter, self).update(iterable) # fast path when counter is empty TypeError: unsupported operand type(s) for +: 'dict' and 'dict' 仅供参考。嵌套的dicts可以没有任何键, 另一个让它更清晰的例子:

clicks

输出:

[
  {
    "25-34": {
      "Clicks": 10,
      "Visits": 1
    },
    "45-54": {
      "Clicks": 2,
      "Visits": 2
    },

  },
  {
    "25-34": {
      "Clicks": 20,
      "Visits": 3
    },
    "45-54": {
      "Clicks": 10,
      "Visits": 4
    },

  }   
]

5 个答案:

答案 0 :(得分:5)

从你的编辑中,听起来你只是试图通过父词汇来总结所有子词的

In [9]: counts = Counter()

In [10]: for dd in data:
    ...:     for k,v in dd.items():
    ...:         counts[k] += sum(v.values())
    ...:

In [11]: counts
Out[11]: Counter({'25-34': 30, '45-54': 12})

从根本上说,这是一个笨拙的数据结构。

好的,鉴于您的上一次更新,我认为最简单的方法是使用defaultdict Counter工厂:

In [17]: from collections import Counter, defaultdict

In [18]: counts = defaultdict(Counter)

In [19]: for dd in data:
    ...:     for k, d in dd.items():
    ...:         counts[k].update(d)
    ...:

In [20]: counts
Out[20]:
defaultdict(collections.Counter,
            {'25-34': Counter({'Clicks': 30, 'Visits': 4}),
             '45-54': Counter({'Clicks': 12, 'Visits': 6})})

答案 1 :(得分:1)

我会使用defaultdict,默认值为int(即0):

from collections import defaultdict
counter = defaultdict(int)

for current_dict in data:
    for key, value in current_dict.items():
        counter[key] += sum(value.values())

在我看来,这是计算值的最可读方式。

答案 2 :(得分:1)

我没有列表理解的变体:

def my_dict_sum(data):
"""
>>> test_data = [{"25-34": {"Clicks": 10, "Visits": 1}, "45-54": {"Clicks": 2, "Visits": 2}, },{"25-34": {"Clicks": 20, "Visits": 3}, "45-54": {"Clicks": 10, "Visits": 4}, }]
>>> my_dict_sum(test_data)
{'45-54': {'Clicks': 12, 'Visits': 6}, '25-34': {'Clicks': 30, 'Visits': 4}}
"""
result_key = data[0]
for x in data[1:]:
    for y in x:
        if y in result_key:
            for z in x[y]:
                if z in result_key[y]:
                    result_key[y][z] = result_key[y][z] + x[y][z]
return result_key

答案 3 :(得分:0)

对于你的第一个问题,这里是一个单行。它不是很漂亮,但确实使用了Counter

sum((Counter({k:v['Clicks'] for k,v in d.items()}) for d in data), Counter())

举个例子:

data = [
  {
    "25-34": {
      "Clicks": 10
    },
    "45-54": {
      "Clicks": 2
    },

  },
  {
    "25-34": {
      "Clicks": 20
    },
    "45-54": {
      "Clicks": 10
    },

  }   
]

from collections import Counter

c = sum((Counter({k:v['Clicks'] for k,v in d.items()}) for d in data), Counter())
print(c)

输出:

Counter({'25-34': 30, '45-54': 12})

答案 4 :(得分:0)

我确实这样:

with gzip.open("data/small_fasta.fa.gz", "rt") as handle:
    aac_count = defaultdict(Counter)
    for record in SeqIO.parse(handle, "fasta"):
        aac_count[record.id].update(record.seq)

我用biopython打开了我经常使用的文件类型fasta文件(https://pt.wikipedia.org/wiki/Formato_FASTA)。

它有一个标头(“ proteinx”),在下一行是一个序列(dna或蛋白质串)。biopython是处理fasta文件的一种简便方法。

然后我将defaultdic和Counter用于集合。 Record.id是标题,是键,我用序列更新计数器,以计算字符串中给定字符的数量。

在我的情况下,输出是这样的:

defaultdict(collections.Counter,
            {'UniRef100_Q6GZX4': Counter({'M': 6,
                      'A': 13,
                      'F': 8,
                      'S': 13,
                      'E': 15,
                      'D': 17,
                      'V': 21,
                      'L': 25,
                      'K': 29,
                      'Y': 14,
                      'R': 15,
                      'P': 11,
                      'N': 8,
                      'W': 4,
                      'Q': 9,
                      'C': 4,
                      'G': 15,
                      'I': 12,
                      'H': 9,
                      'T': 8}),
             'UniRef100_Q6GZX3': Counter({'M': 7,
                      'S': 22,
                      'I': 10,
                      'G': 23,
                      'A': 26,
                      'T': 26,
                      'R': 16,
                      'L': 14,
                      'Q': 13,
                      'N': 9,
                      'D': 24,
                      'K': 17,
                      'Y': 11,
                      'P': 37,
                      'C': 18,
                      'F': 9,
                      'W': 6,
                      'E': 6,
                      'V': 23,
                      'H': 3}),...}