2014-02-25 18 views
4

迭代的長到寬Python單線程(或兩個)我正在尋找使用功能和迭代工具將一個較長的數據集變成一個寬的數據集,我的理解是這是一個groupby任務。我問了幾個關於這個問題之前,以爲我是有,但並不完全在這種情況下,這應該是簡單的:使用groupby

這裏的數據我有:

from itertools import groupby 
from operator import itemgetter 
from pprint import pprint 

>>> longdat=[ 
{"id":"cat", "name" : "best meower", "value": 10}, 
{"id":"cat", "name" : "cleanest paws", "value": 8}, 
{"id":"cat", "name" : "fanciest", "value": 9}, 
{"id":"dog", "name" : "smelly", "value": 9}, 
{"id":"dog", "name" : "dumb", "value": 9}, 
] 

這裏的格式,我希望它在:

>>> widedat=[ 
{"id":"cat", "best meower": 10, "cleanest paws": 8, "fanciest": 9}, 
{"id":"dog", "smelly": 9, "dumb": 9}, 
] 

這裏是我的失敗嘗試:

# WRONG 
>>> gh = groupby(sorted(longdat,key=id),itemgetter('id')) 
>>> list(gh) 
[('cat', <itertools._grouper object at 0x5d0b550>), ('dog', <itertools._grouper object at 0x5d0b210>)] 

確定,需要獲得第二項到迭代的,不夠公平。

#WRONG 
>>> gh = groupby(sorted(longdat,key=id),itemgetter('id')) 
>>> for g,v in gh: 
...  {"id":i["id"], i["name"]:i["value"] for i in v} 
            ^
SyntaxError: invalid syntax 

奇怪,它看起來有效。讓我們展開這些循環來確保。

#WRONG 
gb = groupby(sorted(longdat,key=id),itemgetter('id')) 
data = {} 
for g,v in gb: 
    data[g] = {} 
    for i in v: 
     data[g] = i 

#WRONG 
gb = groupby(sorted(longdat,key=id),itemgetter('id')) 
data = [] 
for g,v in gb: 
    for i in v: 
     data[g] = i 

啊!好的,讓我們回到單行表格

#WRONG 
>>> gb = groupby(sorted(longdat,key=id),itemgetter('id')) 
>>> [{"id":g, i["name"]:i["value"]} for i in k for g,k in gb] 
[] 

什麼?爲什麼是空的?我們基本上正是這一點再次放鬆:

#WRONG 
gb = groupby(sorted(longdat,key=id),itemgetter('id')) 
for g,k in gb: 
    for i in k: 
     print(g, i["name"],i["value"]) 
cat best meower 10 
cat fanciest 9 
cat cleanest paws 8 
dog smelly 9 
dog dumb 9 

現在,這最後一個顯然是最糟糕的---很明顯我的數據是基本上是正確的回到起點,好像我根本就沒GROUPBY。

爲什麼這不起作用,我怎麼能得到我想要的格式?

此外,有可能是爲了這句話完全重複,這樣我可以做

>>> result[0] 
{"id":"cat", "best meower": 10, "cleanest paws": 8, "fanciest": 9} 

,只得到第一個結果,而不處理整個列表(超出其看/所有/其中id == '貓'?)

+1

感謝文字,例子描述了你的問題,並顯示你已經研究了什麼,並企圖。這個寫得很好的問題在這些日子裏是很稀缺的。 – IceArdor

+0

謝謝,IceArdor。人們通常會把它稱爲不必要的冗長。 ;) – Mittenchops

回答

4

key功能傳遞給sorted功能是id。它將返回所有列表項的所有不同值。

它應該是itemgetter('id')lambda x: x.id

>>> id(longdat[0]) 
41859624L 
>>> id(longdat[1]) 
41860488L 
>>> id(longdat[2]) 
41860200L 
>>> itemgetter('id')(longdat[1]) 
'cat' 
>>> itemgetter('id')(longdat[2]) 
'cat' 
>>> itemgetter('id')(longdat[3]) 
'cat' 

from itertools import groupby 
from operator import itemgetter 

longdat = [ 
    {"id":"cat", "name" : "best meower", "value": 10}, 
    {"id":"cat", "name" : "cleanest paws", "value": 8}, 
    {"id":"cat", "name" : "fanciest", "value": 9}, 
    {"id":"dog", "name" : "smelly", "value": 9}, 
    {"id":"dog", "name" : "dumb", "value": 9}, 
] 

getid = itemgetter('id') 
result = [ 
    dict([['id', key]] + [[d['name'], d['value']] for d in grp]) 
    for key, grp in groupby(sorted(longdat, key=getid), key=getid) 
] 
print(result) 

輸出:

[{'best meower': 10, 'fanciest': 9, 'id': 'cat', 'cleanest paws': 8}, 
{'dumb': 9, 'smelly': 9, 'id': 'dog'}] 
+0

當我嘗試用'[{'id':key,d ['name']:d ['value']替換您的dict([[]] + [[]])語法時, d in grp for key,grp in gb]'不應該和{}構造函數而不是dict()函數一樣嗎? – Mittenchops

+0

@Mittenchops,你的意思是詞典理解?我不知道如何使用詞典理解而不使用迭代[[..]] + [[..]]或'itertools.chain ...' – falsetru

+1

@Mittenchops,如果您想使用詞典理解,請參見[這個](http://ideone.com/To88FA)。順便說一句,它更長一點。 – falsetru