2012-10-05 50 views
3

這裏是python的新增內容。我一直拉我的頭髮幾個小時,仍然無法弄清楚這一點。將列表中的類似詞典合併到一起

我的詞典列表:

[ {'FX0XST001.MID5': '195', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'} 
    {'FX0XST001.MID13': '4929', 'Name': 'Firmicutes', 'Taxonomy ID': '1239','Type': 'phylum'}, 
    {'FX0XST001.MID6': '826', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'}, 
             . 
             . 
             . 
             . 

    {'FX0XST001.MID6': '125', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'} 
    {'FX0XST001.MID25': '70', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'} 
    {'FX0XST001.MID40': '40', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'} ] 

我想根據自己的類型,名稱合併在列表中的詞典,分類ID

[ {'FX0XST001.MID5': '195', 'FX0XST001.MID13': '4929', 'FX0XST001.MID6': '826', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'} 
             . 
             . 
             . 
             . 

    {'FX0XST001.MID6': '125', 'FX0XST001.MID25': '70', 'FX0XST001.MID40': '40', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'}] 

我有數據結構設置像這樣,因爲我需要稍後使用csv.DictWriter將數據寫入CSV。

會有人指點我正確的方向嗎?

+1

標籤('FX ...')以及看起來像這些項目的ID是另一個關鍵字:這些項目的屬性字典中的值對是什麼?從頭開始看起來是錯誤的,你怎麼知道哪個鍵是標籤?因爲它以'FX ...'開始?因爲它是唯一不是類型,名稱或分類標識? –

+1

您的數據不是二維的,因此不適合csv文件。(每個鍵對應一列 - 但在您的數據中,每個字典將具有不同的鍵。) –

+0

我可能可以改進我的數據結構。基本上我需要'Type','Name'和'Taxonomy'的值作爲我的行標籤,'FX ... MID ..'的值就是數據。 'FX..MID ...'是我的專欄標籤 – WonderSteve

回答

5

可以使用GROUPBY功能如下:

http://docs.python.org/library/itertools.html#itertools.groupby

from itertools import groupby 

keyfunc = lambda row : (row['Type'], row['Taxonomy ID'], row['Name']) 

result = [] 

data = sorted(data, key=keyfunc) 
for k, g in groupby(data, keyfunc): 
    # you can either add the matching rows to the item so you end up with what you wanted 
    item = {}   
    for row in g: 
     item.update(row) 
    result.append(item) 

    # or you could just add the matched rows as subitems to a parent dictionary 
    # which might come in handy if you need to work with just the parts that are 
    # different 
    item = {'Type': k[0], 'Taxonomy ID' : k[1], 'Name' : k[2], 'matches': []) 
    for row in g: 
     del row['Type'] 
     del row['Taxonomy ID'] 
     del row['Name'] 
     item['matches'].append(row) 
    result.append(item) 
+0

不錯!我可以使用'itertools.groupby'完成它,但是直到你發佈你的答案才能工作:) –

+0

謝謝你很多!我真的需要更多地瞭解itertools中的東西! – WonderSteve

+0

不需要外部循環的fisrt 2行 – dugres

2

也許是最容易做的事情是創建一個新的字典,通過索引(類型,名稱,分類ID)元組,迭代你的字典,按(Type,Name,Taxonomy ID)存儲值。使用默認詞典來簡化操作。例如:

from collections import defaultdict 
grouped = defaultdict(lambda : {}) 

# iterate over items and store: 
for entry in list_of_dictionaries: 
    grouped[(entry["Type"], entry["Name"], entry["Taxonomy ID"])].update(entry) 

# now you have everything stored the way you want in values, and you don't 
# need the dict anymore 
grouped_entries = grouped.values() 

這是一個有點hackish,特別是因爲你最終覆蓋「類型」,「名稱」和「語系」每次使用update時間,但因爲你的字典鍵是可變的,這可能成爲你能做的最好的。這會讓你至少接近你所需要的。

更好的辦法是在初次導入時執行此操作並跳過中間步驟(除非事實上需要事先轉換數據)。另外,如果你能在只有變場得到,你可以改變update只是:grouped[(type, name, taxonomy_id)][key] = value,其中鍵和值是這樣的:「FX0XST001.MID5」,「195」

+0

所以這會產生一個字典(Type,Name,Taxonomy ID)作爲關鍵字其餘值爲? – WonderSteve

+0

@WonderSteve,是的,與groupby相比,唯一的優勢是可以在導入時使用它跳過中間數據結構,如果使用'update'方法,'Type','Name'和'Taxonomy ID'也將在字典中。 –

3

做一些測試數據:

list_of_dicts = [ 
       {"Taxonomy ID":1, "Name":"Bob", "Type":"M", "hair":"brown", "eyes":"green"}, 
       {"Taxonomy ID":1, "Name":"Bob", "Type":"M", "height":"6'2''", "weight":200}, 
       {"Taxonomy ID":2, "Name":"Alice", "Type":"F", "hair":"black", "eyes":"hazel"}, 
       {"Taxonomy ID":2, "Name":"Alice", "Type":"F", "height":"5'7''", "weight":145} 
       ]  

我認爲這個(下面)使用reduce是一個巧妙的把戲,它改進了其他groupby解決方案。

import itertools 
def key_func(elem): 
    return (elem["Taxonomy ID"], elem["Name"], elem["Type"]) 

output_list_of_dicts = [reduce((lambda x,y: x.update(y) or x), list(val)) for key, val in itertools.groupby(list_of_dicts, key_func)] 

然後打印輸出:

for elem in output_list_of_dicts: 
    print elem 

此打印:

{'eyes': 'green', 'Name': 'Bob', 'weight': 200, 'Taxonomy ID': 1, 'hair': 'brown', 'height': "6'2''", 'Type': 'M'} 
{'eyes': 'hazel', 'Name': 'Alice', 'weight': 145, 'Taxonomy ID': 2, 'hair': 'black', 'height': "5'7''", 'Type': 'F'} 

僅供參考,Python Pandas更好地爲這種聚合的,尤其是與文件打交道時,I/O到.csv或.h5文件,比itertools的東西。

+0

謝謝!我將檢查Python熊貓 – WonderSteve

0
from itertools import groupby 

data = [ {'FX0XST001.MID5': '195', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type':'phylum'}, 
    {'FX0XST001.MID13': '4929', 'Name': 'Firmicutes', 'Taxonomy ID': '1239','Type': 'phylum'}, 
    {'FX0XST001.MID6': '826', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'}, 
    {'FX0XST001.MID6': '125', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'}, 
    {'FX0XST001.MID25': '70', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'}, 
    {'FX0XST001.MID40': '40', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'} ,] 

kk = ('Name', 'Taxonomy ID', 'Type') 

def key(item): return tuple(item[k] for k in kk) 

result = [] 
data = sorted(data, key=key) 
for k, g in groupby(data, key): 
    result.append(dict((i, j) for d in g for i,j in d.items())) 


print result 
相關問題