2014-03-06 51 views
1

我有几百元组在下面的格式(ID1,ID2,ID3,[xydata])例如:合并元组的一部分,在Python

('a', 'b', 'c', [(1, 2),(2, 3),(3, 4)]) 
('a', 'b', 'c', [(1, 1),(2, 4),(3, 6)]) 
('a', 'b', 'd', [(1, 3),(2, 6),(3, 7)]) 
('a', 'b', 'd', [(1, 7),(2, 8),(3, 9)]) 

现在我要合并的元组让那些以相同的三个值开始以下列方式组合。我保证相同的X值在所有xydata:

('a', 'b', 'c', [(1, mean(2, 1)),(2, mean(3, 4)),(3, mean(4, 6))]) 
('a', 'b', 'd', [(1, mean(3, 7)),(2, mean(6, 8)),(3, mean(7, 9))]) 

目前的解决方案需要几个步骤重新排序和打出来的数据,将它们结合起来,重建原始数据结构之前存储在多层字典中的元组。是否有一种整洁和Pythonic的方式来做到这一点?

+0

项目1,2和3被固定或可以是任何东西? –

+1

我不禁觉得这可能更容易在数据库中完成。 –

+0

@Ashwini:id1,id2和id3是字符串,用于标识数据。 Xydata是[(integer,float)]的列表 – pehrs

回答

1

您可以通过使用defaultdict合并:

>>> l = [('a', 'b', 'c', [(1, 2),(2, 3),(3, 4)]), 
...  ('a', 'b', 'c', [(1, 1),(2, 4),(3, 6)]), 
...  ('a', 'b', 'd', [(1, 3),(2, 6),(3, 7)]), 
...  ('a', 'b', 'd', [(1, 7),(2, 8),(3, 9)])] 

>>> d = defaultdict(lambda:defaultdict(list)) 
>>> for k1,k2,k3, lst in l: 
... for t in lst: 
... d[(k1,k2,k3)][t[0]].append(t[1]) 

结果:

>>> d 
defaultdict(<function <lambda> at 0x8e33e9c>, 
{('a', 'b', 'c'): defaultdict(<type 'list'>, {1: [2, 1], 2: [3, 4], 3: [4, 6]}), 
('a', 'b', 'd'): defaultdict(<type 'list'>, {1: [3, 7], 2: [6, 8], 3: [7, 9]})}) 

,如果你需要它在列表:

>>> [(k, v.items()) for k,v in d.items()] 
[(('a', 'b', 'c'), [(1, [2, 1]), (2, [3, 4]), (3, [4, 6])]), 
(('a', 'b', 'd'), [(1, [3, 7]), (2, [6, 8]), (3, [7, 9])])] 

均值计算:

>>> [(k, [(n, sum(t)/float(len(t))) for n,t in v.items()]) for k,v in d.items()] 
[(('a', 'b', 'c'), [(1, 1.5), (2, 3.5), (3, 5.0)]), 
(('a', 'b', 'd'), [(1, 5.0), (2, 7.0), (3, 8.0)])] 
+1

Very整洁,我不知道defaultdict,这使事情变得更容易。 – pehrs

2

使用itertools.groupbyizip和一些列表理解:

from itertools import groupby, izip 
from pprint import pprint 

lis = [('a', 'b', 'c', [(1, 2), (2, 3), (3, 4)]), ('a', 'b', 'c', [(1, 1), (2, 4), (3, 6)]), ('a', 'b', 'd', [(1, 3), (2, 6), (3, 7)]), ('a', 'b', 'd', [(1, 7), (2, 8), (3, 9)])] 

def solve(seq, X): 
    for k, g in groupby(seq, key=lambda x:x[:3]): 
     data = ((y[1] for y in x[3]) for x in g) 
     yield tuple(list(k) + [[(a, sum(b, 0.0)/len(b)) 
               for a, b in izip(X, izip(*data))]]) 

X = [a for a, _ in lis[0][3]] 
pprint(list(solve(lis, X))) 

输出:

[('a', 'b', 'c', [(1, 1.5), (2, 3.5), (3, 5.0)]), 
('a', 'b', 'd', [(1, 5.0), (2, 7.0), (3, 8.0)])]