2017-08-22 101 views
2

我试图获得2个不同列表的聚合,其中每个元素是包含2个条目的月份和值的字典。基于Python中的键的字典列表的聚合值

所以第一清单如下:

[{ 
    'patient_notes': 5, 
    'month': datetime.date(2017, 1, 1) 
}, { 
    'patient_notes': 5, 
    'month': datetime.date(2017, 2, 1) 
}, { 
    'patient_notes': 5, 
    'month': datetime.date(2017, 5, 1) 
}, { 
    'patient_notes': 5, 
    'month': datetime.date(2017, 7, 1) 
}, { 
    'patient_notes': 5, 
    'month': datetime.date(2017, 8, 1) 
}, { 
    'patient_notes': 5, 
    'month': datetime.date(2017, 12, 1) 
}] 

第二表:

[{ 
    'employee_notes': 4, 
    'month': datetime.date(2017, 2, 1) 
}, { 
    'employee_notes': 4, 
    'month': datetime.date(2017, 3, 1) 
}, { 
    'employee_notes': 4, 
    'month': datetime.date(2017, 4, 1) 
}, { 
    'employee_notes': 4, 
    'month': datetime.date(2017, 8, 1) 
}, { 
    'employee_notes': 4, 
    'month': datetime.date(2017, 9, 1) 
}, { 
    'employee_notes': 4, 
    'month': datetime.date(2017, 10, 1) 
}, { 
    'employee_notes': 4, 
    'month': datetime.date(2017, 12, 1) 
}] 

所以我需要建立一个包含每月两个列表的和一个新的列表,像这个:

[{ 
    'total_messages': 14, 
    'month': '2017-01-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-02-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-03-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-04-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-05-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-06-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-07-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-08-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-09-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-10-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-11-01' 
}, { 
    'total_messages': 14, 
    'month': '2017-12-01' 
}] 

我第一次尝试使用zip,但这只适用于如果前2列表大小相等。然后我尝试了[itertools.izip_longest],但是如果列表的大小相同但是月份不同,则会出现问题...我不能简单地聚合这些...我只需要累计匹配的月份

Counter也非常适合这种情况,但我不能更改原始列表的键名...有什么想法?

+3

添加你的努力 – Dekel

+0

你是如何加入'patient_notes'和'employee_notes'的代码? – Antimony

+0

看起来像熊猫的问题。 – DyZ

回答

3

您可以使用defaultdict创建一个计数器。遍历第一个列表中的每个项目并将patient_notes值添加到字典中。然后通过第二个列表并添加employee_notes值。

现在您需要将您的新defaultdict编码回您想要的格式的列表中。你可以使用列表理解。我已经按月排序了。

from collections import defaultdict 

dd = defaultdict(int) 

for d in my_list_1: 
    dd[d['month']] += d['patient_notes'] 
for d in my_list_2: 
    dd[d['month']] += d['employee_notes'] 

result = [{'total_messages': dd[k], 'month': k} for k in sorted(dd.keys())] 
>>> result 
[{'month': datetime.date(2017, 1, 1), 'total_messages': 5}, 
{'month': datetime.date(2017, 2, 1), 'total_messages': 9}, 
{'month': datetime.date(2017, 3, 1), 'total_messages': 4}, 
{'month': datetime.date(2017, 4, 1), 'total_messages': 4}, 
{'month': datetime.date(2017, 5, 1), 'total_messages': 5}, 
{'month': datetime.date(2017, 7, 1), 'total_messages': 5}, 
{'month': datetime.date(2017, 8, 1), 'total_messages': 9}, 
{'month': datetime.date(2017, 9, 1), 'total_messages': 4}, 
{'month': datetime.date(2017, 10, 1), 'total_messages': 4}, 
{'month': datetime.date(2017, 12, 1), 'total_messages': 9}] 
+0

很整洁!没有考虑使用字典来汇总值,谢谢@亚历山大 – AlejandroVK

2
from collections import defaultdict 
d_dict = defaultdict(int) 
for k,v in [ i.values() for i in l1 + l2 ]: 
    d_dict[k] += v 
[ {'month':i.strftime("%Y-%m-%d"),'total_messages':j} for i, j in sorted(d_dict.items()) ] 

输出:

[{'month': '2017-01-01', 'total_messages': 5}, 
{'month': '2017-02-01', 'total_messages': 9}, 
{'month': '2017-03-01', 'total_messages': 4}, 
{'month': '2017-04-01', 'total_messages': 4}, 
{'month': '2017-05-01', 'total_messages': 5}, 
{'month': '2017-07-01', 'total_messages': 5}, 
{'month': '2017-08-01', 'total_messages': 9}, 
{'month': '2017-09-01', 'total_messages': 4}, 
{'month': '2017-10-01', 'total_messages': 4}, 
{'month': '2017-12-01', 'total_messages': 9}] 
+0

我不太明白'for k,v'部分---不会'values()'返回一个数字列表吗? – patrick

+1

@patrick - 如果您观察,输入列表是词典列表... i.values()将获得列表中每个词典的值... [(date1,num1),(date2,num2)... 。等] – Transhuman

+1

从OP输出,我们可以通过使用值忽略字典键的逻辑来实现它。 – Transhuman

相关问题