如果一个字典的键(元组)相似,Python如何对其元素求和?

3

我有一个单一的字典,看起来像这样:

{('20144', 'Wirtschaftskammer Österreich Fachverband der Telekommunikations- und Rundfunkunternehmungen', 'Bezirksrundschau Oberösterreich', '4'): 12321.88, ('20143', 'Wirtschaftskammer Niederösterreich Fachgruppe Unternehmensberatung und Informationstechnologie NÖ', 'trend', '31'): 5700.53, ('20144', 'Wirtschaftskammer Tirol - Sparte Gewerbe und Handwerk Innung der Lebensmittelgewerbe', 'ORF Radio Tirol', '4'): 5861.56, ('20144', 'Bundesministerium für Land- und Forstwirtschaft Umwelt und Wasserwirtschaft', 'Weekend Magazin', '2'): 17355.1, ('20144', 'Bundesministerium für Land- und Forstwirtschaft Umwelt und Wasserwirtschaft', 'Woman', '2'): 12911.5, ('20144', 'Bundesministerium für Wissenschaft Forschung und Wirtschaft', 'Die Presse', '31'): 30965.4, ('20143', 'Bundesministerium für Europa Integration und Äußeres', 'Kronen Zeitung', '4'): 52490.46,.......)}

我想将所有键前面数字相同(例如20144)且末尾数字也相同(例如231)的值求和。

我考虑使用字典推导式,但是我在比较所需的键时遇到了困难。如何轻松比较它们?


1
如果第一个数字是20144,但最后一个数字是231,那么它会被归入同一个总和还是两个不同的总和? - LMc
这将是两个不同的求和。 - IamnotaRabbit
4个回答

1
解决方案:
trimmed={}
for k,v in data.items(): 
    trimmed.setdefault((k[0],k[-1]),[]).append(v)

{k:sum(v) for k,v in trimmed.items()} 

输出:

{('20144', '4'): 18183.44, ('20144', '31'): 30965.4, ('20143', '31'): 5700.53, ('20144', '2'): 30266.6, ('20143', '4'): 52490.46}

鉴于您的示例,这是在for循环后trimmed的样子:
{('20144', '4'): [12321.88, 5861.56], ('20144', '31'): [30965.4], ('20143', '4'): [52490.46], ('20144', '2'): [12911.5, 17355.1], ('20143', '31'): [5700.53]}

解释:

for循环遍历你的样本数据中的数据键(k)和键值(v)。如果键(k[0], k[-1])(即键元组中的第一个和最后一个值--例如:('20144', '4'))在新字典trimmed中不存在,则创建一个空列表并添加该值(v)。如果该键已存在,则仅将其值附加到现有列表中。

完成trimmed字典后,简单的字典推导式对所有这些列表进行求和。

编辑:

如评论中所指出,如果性能是一个问题,则还可以使用collections中的defaultdict

from collections import defaultdict

trimmed=defaultdict(float)
for k,v in data.items(): 
    trimmed[(k[0],k[-1])]+=v

在这里,值存储在trimmed中。在trimmed defaultdict中新初始化的键将是0.0。然后你可以直接就地添加v

使用defaultdict代替setdefault。这通常会更快,并且更易于阅读。而且,你可以将默认值设置为零并进行求和,而不是默认为列表。 - juanpa.arrivillaga
感谢您的解释和解决方案! :-) 我完全理解了这是如何工作的! - IamnotaRabbit

1
这可以让你得到你想要的结果:

dict = {('20144', 'Bundesministerium f\xc3\xbcr Land- und Forstwirtschaft Umwelt und Wasserwirtschaft', 'Woman', '2'): 12911.5, ('20144', 'Wirtschaftskammer Tirol - Sparte Gewerbe und Handwerk Innung der Lebensmittelgewerbe', 'ORF Radio Tirol', '4'): 5861.56, ('20144', 'Bundesministerium f\xc3\xbcr Land- und Forstwirtschaft Umwelt und Wasserwirtschaft', 'Weekend Magazin', '2'): 17355.1, ('20144', 'Bundesministerium f\xc3\xbcr Wissenschaft Forschung und Wirtschaft', 'Die Presse', '31'): 30965.4, ('20144', 'Wirtschaftskammer \xc3\x96sterreich Fachverband der Telekommunikations- und Rundfunkunternehmungen', 'Bezirksrundschau Ober\xc3\xb6sterreich', '4'): 12321.88, ('20143', 'Wirtschaftskammer Nieder\xc3\xb6sterreich Fachgruppe Unternehmensberatung und Informationstechnologie N\xc3\x96', 'trend', '31'): 5700.53, ('20143', 'Bundesministerium f\xc3\xbcr Europa Integration und \xc3\x84u\xc3\x9feres', 'Kronen Zeitung', '4'): 52490.46}
sum_by_key = {}
filter_obj = None
for key, value in dict.items():
  sum_key = (key[0], key[-1])
  if sum_key in sum_by_key:
    sum_by_key[sum_key] += value
  else:
    sum_by_key[sum_key] = value

输出:

{('20144', '2'): 30266.6, ('20143', '31'): 5700.53, ('20144', '31'): 30965.4, ('20144', '4'): 18183.44, ('20143', '4'): 52490.46}

1
谢谢!这帮了很多忙! - IamnotaRabbit

0
你可以使用 itertools.groupby。看看下面的代码是否适合你(我使用了 d 作为你的字典)。 编辑:需要对字典进行排序
fields = lambda k: (k[0], k[3])
for k, i in itertools.groupby(sorted(d, key=fields), key=fields):
    ...:     print(k, sum(d[v] for v in i))

('20143', '31') 5700.53
('20143', '4') 524.23
('20144', '2') 30266.6
('20144', '31') 30965.4
('20144', '4') 18183.44

很遗憾,这不起作用 :-( 我得到了这个错误:KeyError: (('20144','Salzburg AG für Energie Verkehr und Telekommunikation','Bezirksblätter Salzburg','2'),27166.75) - IamnotaRabbit
('20143', '欧洲一体化和外交部', 'Kronen Zeitung', '4'): 52490.46。 - LMc
@LMc:是的,我在删除末尾的点时更改了值。 - matiasg
@matiasg 不错,只是想指出你的代码输出了正确的结果,但你在这里打印的输出是不正确的。请看 ('20143', '4') 524.23 和我上面的评论。 - LMc

0

以下是如何利用标准库中的defaultdict一次性完成的方法:

import collections
output_dict = collections.defaultdict(float)
for key, value in input_dict.items():
    output_dict[ (key[0], key[-1]) ] += value


# show the output
print('\n'.join('%r: %r' % (key,value) for key, value in output_dict.items()))

输出如下:

('20144', '2'): 30266.6
('20143', '31'): 5700.53
('20144', '31'): 30965.4
('20144', '4'): 18183.44
('20143', '4'): 52490.46

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接