2015-10-14 40 views
1

我有一个电子表格,其中包含不同类别的数据,我从csv读入字典并将其作为关键字。来自Python字典数据的成对组合

我想从数据中创建成对组合,但似乎只能将键组合出来。

例如,如果我的数据是

{"x":['1','2','3'], 
"y":['4','5'], 
"z":['puddi']} 

我使用itertools和itervalues(从here代码),我可以做如下计算出:

[{"x":['1','2','3'],"y":['4','5'}, 
{"x":['1','2','3'],"z":['puddi']}, 
...] 

我知道itervalues回报我想用来做我的成对组合的价值,而itertools.product会产生我想要的组合,但我努力将它们一起带入所需的格式:

{"x":['1','2','3','1','2','3'...], 
"y":['4','5','4',....], 
"z":['puddi','puddi','....]} 

任何帮助将是非常有用

+0

非常感谢解决方案的人,他们真的很有帮助。 但我意识到我在我的问题上犯了一个错误; itertools。产品将给我详尽的/ cartessian组合,而我想要所有对/成对组合(我的示例数据的形状产生相同数量的穷举/ cartessian组合和成对我感到困惑)。 所以我现在所做的是使用OrderedDict对数值进行排序,并尝试使用前两行执行一个产品,然后使用其他行中的交替数值填充剩余空间 – TesenkaNoMai

回答

0

如果我们可以假设你知道字典键事前,一个办法做到这一点是 -

from itertools import product 
result = {'x':[],'y':[],'z':[]} 
for a,b,c in product(data['x'],data['y'],data['z']): #data is the original dictionary 
    result['x'].append(a) 
    result['y'].append(b) 
    result['z'].append(c) 

上述发送列表(字典中的值)设置为itertools.product,然后将itertools.product产生的每个组合/产品都添加到结果字典的列表中。

演示 -

>>> data = {"x":['1','2','3'], 
... "y":['4','5'], 
... "z":['puddi']} 
>>> 
>>> from itertools import product 
>>> result = {'x':[],'y':[],'z':[]} 
>>> for a,b,c in product(data['x'],data['y'],data['z']): 
...  result['x'].append(a) 
...  result['y'].append(b) 
...  result['z'].append(c) 
... 
>>> pprint.pprint(result) 
{'x': ['1', '1', '2', '2', '3', '3'], 
'y': ['4', '5', '4', '5', '4', '5'], 
'z': ['puddi', 'puddi', 'puddi', 'puddi', 'puddi', 'puddi']} 

一个通用的解决方案 -

keys = list(data.keys()) #Or the list of keys you want Ex. - keys = ['x','y'] 
result = {k:[] for k in keys} 
import operator 
for item in product(*operator.itemgetter(*keys)(data)): 
    for i, k in enumerate(keys): 
      result[k].append(item[i]) 

演示 -

>>> keys = list(data.keys()) 
>>> result = {k:[] for k in keys} 
>>> import operator 
>>> for item in product(*operator.itemgetter(*keys)(data)): 
...  for i, k in enumerate(keys): 
...    result[k].append(item[i]) 
... 
>>> pprint.pprint(result) 
{'x': ['1', '2', '3', '1', '2', '3'], 
'y': ['4', '4', '4', '5', '5', '5'], 
'z': ['puddi', 'puddi', 'puddi', 'puddi', 'puddi', 'puddi']} 
+0

* operater究竟是什么.itemgetter(*键)(数据)在干什么?在你的静态解决方案中,你已经清楚地得到了你的乘法的3个集合,但是这个引用返回的是什么? – TesenkaNoMai

+0

operator.itemgetter(* keys)(data)根据key'列表中的键返回数据列表。开始处的'*'运算符和'(*键)'用于解包,不能相乘 –

+0

感谢那 另外,如果我只想找到x和y的乘积,我该如何指定一个范围的键。我已经尝试将*键改为*键[0:1],但是这样做有些奇怪,并且键只能得到一个值。 – TesenkaNoMai

0

这里有一种方法:

d = {"x":['1','2','3'], 
"y":['4','5'], 
"z":['puddi']} 
>>> {k: list(v) for k, v in zip(d.keys(), zip(*itertools.product(*d.values())))} 
{'x': ['1', '2', '3', '1', '2', '3'], 
'y': ['4', '4', '4', '5', '5', '5'], 
'z': ['puddi', 'puddi', 'puddi', 'puddi', 'puddi', 'puddi']} 

正如你所说,itertools.product上的值创建了你想要的数据,但是它被转置以便数据处于“行”而不是“列”(即第一行是"4", "1", "puddi)。在这个上使用zip(*...)转换它,所以你得到每一列的一个元组。然后,您可以用原始密钥对其进行压缩,以使用原始密钥重新对齐每列。

您无法控制产品中行的顺序,因为这取决于字典中键的顺序,而顺序是任意的。 (但是,因为documented,dict确实保证调用values,然后keys会生成对齐的值,这就是为什么可以像上面那样分别调用它们是安全的。)如果您需要控制行的顺序,则必须除了你的字典之外还可以使用一些有序的结构(例如,下面的Anand的答案中的一个单独的键列表)。