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。

有人会指出我正确的方向吗?

4

4 回答 4

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)  
于 2012-10-05T21:18:53.450 回答
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对于这种聚合要好得多,尤其是在处理 .csv 或 .h5 文件的文件 I/O 时,比其他东西itertools要好得多。

于 2012-10-05T21:31:05.477 回答
2

也许最简单的做法是创建一个新字典,由 (Type, Name, Taxonomy ID) 元组索引,然后遍历您的字典,按 (Type, Name, Taxonomy ID) 存储值。使用默认 dict 使这更容易。例如:

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

这有点骇人听闻,特别是因为您每次使用时都会覆盖“Type”、“Name”和“Phylum” update,但由于您的 dict 键是可变的,这可能是您能做的最好的事情。这会让你至少接近你需要的东西。

更好的是在您的初始导入中执行此操作并跳过中间步骤(除非您实际上需要事先转换数据)。另外,如果您可以获取唯一的可变字段,则可以将其更改update为:grouped[(type, name, taxonomy_id)][key] = value其中键和值类似于:'FX0XST001.MID5','195'

于 2012-10-05T21:23:32.400 回答
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
于 2012-10-05T22:15:07.503 回答