2014-12-01 18 views
3

的總和值我回答了另一個OP的question關於如何添加嵌套字典中的不同項目,我想出了一個三嵌套for循環方法來在三級詞典中添加項目,這是可行的,但meeeh ...我很確定它可以做得更簡潔。壁壘和3線嵌套字典在單線(或兩線)

爲了提供一個真正的用例場景:比方說,我有一個攝像頭在一些商店的門口,計數有多少人走走出商店 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, 
      }, 
     }, 
} 

我想壁球這些字典在一起,通過一個特定的時間,加上插件出局將它們分組不分日期的。比方說,我想知道「有多少人進入和離開我的場地,無論日期爲」還是使用不同的措辭「我想知道從那以後總共有多少次輸入和輸出每次斗的時候開始「

這將是添加插件出局對於其鍵中的所有類型的字典的結果是時間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對象的列表(然後我不知道該怎麼處理它們),或者我得到一個錯誤,因爲我試圖添加兩個dict s ...

我知道真的不是很大(3個for循環完成工作),但我很好奇這個的可行性,以及如何縮短我的代碼(並可能瞭解itertools,這是關於時間...)

謝謝你提前。

+0

我想你可以用'sorted'和['itertools.groupby'](https://docs.python.org/2/library/itertools.html#itertools.groupby)的組合來完成它,但我不會現在沒有時間留下詳細的答案。 – 2014-12-01 16:42:37

+0

你的代碼應該可以翻譯成一個很好的單行列表comp,但它會有點長和雜亂,可能沒有功能上的不同。也許發佈你的代碼? – user2782067 2014-12-01 16:43:47

+0

@ user2782067,我可以想出最好的東西(嗯......我可以使用'values()'的時候濫用'keys()',但我其實並不在乎這麼多)回答提示這個問題(這個答案:http://stackoverflow.com/a/27217180/289011) – BorrajaX 2014-12-01 16:45:46

回答

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

僅僅因爲一些可以做並不意味着它應該來完成。我會用最明確的解決方案,而不是這樣。

+0

yawwwzaa ...是的,我同意......它看起來比我想象的要醜陋**: - D ** – BorrajaX 2014-12-02 16:26:50

1

你可以使用熊貓DataFrames: https://stackoverflow.com/a/18162021/764322

這將是2號線,一到你想要的條件,創建數據幀(folowings前面的問題回答),另一種做一個簡單的numpy的總和()這也可以添加在線的末尾,並使其成爲單線(雖然很長)。

更新:代碼不是... ...

# 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 
+0

我會看看它。不過,我希望使用內置插件。感謝你的回答! – BorrajaX 2014-12-01 16:40:06

+0

使用熊貓編寫解決方案,以防萬一您仍然感興趣。 – 2014-12-02 11:04:59

+0

這當然是有效的,有趣的(可能*正確的方式來完成我所要求的),但它似乎偏離了問題的原始精神。它絕對值得* upvote *(肯定)。 – BorrajaX 2014-12-02 14:11:54

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})}