我正在回答另一个关于如何在嵌套词典中添加不同项目的OP question,我想出了一个三嵌套for
循环方法来在三级词典中添加项目,哪个有效,但是meeeh ......我很确定它可以更简洁地完成。
提供一个真实的用例场景:假设我在一些商店的入口处有一些来自摄像头的数据,这些数据计算和中有多少人走以10分钟的间隔> 商店:
data = {
"2014/01/01": {
"15:00:00" : {
"ins": 7,
"outs": 5,
},
"15:10:00" : {
"ins": 24,
"outs": 10,
},
"15:20:00" : {
"ins": 10,
"outs": 20,
},
},
"2014/01/02": {
"15:00:00" : {
"ins": 10,
"outs": 10,
},
"15:10:00" : {
"ins": 12,
"outs": 5,
},
"15:20:00" : {
"ins": 5,
"outs": 10,
},
},
}
我希望压缩这些词典,然后添加 ins 和 out 将它们按特定时间分组,无论日期。让我们说我想知道" 每个时间段有多少人进出我的场地,无论日期"或者用不同的措辞"我想知道自每个时间段开始以来总共有多少来龙去掉"
这是为{{1}中找到的密钥为 time 的所有词干添加 ins 和 out 的结果dict(忽略第一个日期"级别")使用上面提供的示例data
,这将是:
data
从"15:00:00": {
"ins": 17 # (7 + 10)
"outs": 15 # (5 + 10)
},
"15:10:00": {
"ins": 36 # (24 + 12)
"outs": 15 # (10 + 5)
},
"15:20:00": {
"ins": 15 # (10 + 5)
"outs": 30 # (20 + 10)
}
开始,有某种方式......某种方式(我通过itertools进行猜测,但我不知道哪些工具是正确的) ,最终得到上面显示的结果在一行(或两行)?
我一直在摆弄
中找到的答案但我无法弄清楚如何得到我想要的东西。我要么获得data
个对象的列表(然后我不知道如何处理它们),否则我会收到错误,因为我试图添加两个Counter
s。 ..
我知道这并不是什么大问题(三个dict
循环完成工作),但我很好奇这个的可行性,以及如何缩短我的代码(并且可能了解{{ 1}},这是关于时间......)
提前谢谢。
答案 0 :(得分:2)
它比两行长一点,但是:
from collections import Counter, defaultdict
flattened = (time for day in data.itervalues() for time in day.iteritems())
sums = defaultdict(lambda: Counter())
for time, entries in flattened:
sums[time] += Counter(entries)
给出:
In [116]: dict(sums)
Out[116]:
{'15:00:00': Counter({'ins': 17, 'outs': 15}),
'15:10:00': Counter({'ins': 36, 'outs': 15}),
'15:20:00': Counter({'outs': 30, 'ins': 15})}
答案 1 :(得分:1)
您可以使用pandas DataFrames: https://stackoverflow.com/a/18162021/764322
它将是2行,一个用于创建数据帧(以下是前面的问题回答),另一个用于根据需要进行简单的numpy sum(),也可以在行的末尾添加并生成它是一个单行(虽然很长)。
更新:代码不是那种...
# Create data frame
>>> table = pd.DataFrame([[c2, d2['ins'], d2['outs']] for d1 in data.values() for c2, d2 in d1.items()])
>>> table
0 1 2
0 15:20:00 5 10
1 15:00:00 10 10
2 15:10:00 12 5
3 15:20:00 10 20
4 15:00:00 7 5
5 15:10:00 24 10
[6 rows x 3 columns]
第1列为ins
,2为outs
。
>>> table.groupby(0).sum()
1 2
0
15:00:00 17 15
15:10:00 36 15
15:20:00 15 30
答案 2 :(得分:1)
是的,它可以作为一个班轮来完成。我把它分成了两行,即便如此,它还是不可读的。
flattened = sorted((time,key,count) for day in data.values() for time,counters in day.items() for key,count in counters.items())
{time:{key:sum(datum[2] for datum in counters) for key,counters in itertools.groupby(group, lambda x:x[1])} for time,group in itertools.groupby(flattened, lambda x:x[0])}
{'15:20:00': {'outs': 30, 'ins': 15}, '15:00:00': {'outs': 15, 'ins': 17}, '15:10:00': {'outs': 15, 'ins': 36}}
仅仅因为某些可以完成并不意味着应该完成。我会选择最清晰的解决方案,但事实并非如此。