单行(或双行)中3级嵌套词典的壁球和总和值

时间:2014-12-01 16:29:12

标签: python dictionary grouping

我正在回答另一个关于如何在嵌套词典中添加不同项目的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}},这是关于时间......)

提前谢谢。

3 个答案:

答案 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}}

仅仅因为某些可以完成并不意味着应该完成。我会选择最清晰的解决方案,但事实并非如此。