2017-07-31 67 views
2

给出一个数据帧:与其自身熊猫数据帧的笛卡尔乘积

id value 
0 1  a 
1 2  b 
2 3  c 

我希望得到一个新的数据帧,基本上是每一行与每一其他行的笛卡尔积不包括本身

id value id_2 value_2 
0 1  a  2 b 
1 1  a  3 c 
2 2  b  1 a 
3 2  b  3 c 
4 3  c  1 a 
5 3  c  2 b 

这是我到现在为止的方法。我用itertools获得产品,然后使用pd.concatdf.loc以获取新的数据帧。

from itertools import product 

ids = df.index.values 
ids_1, ids_2 = list(zip(*filter(lambda x: x[0] != x[1], product(ids, ids)))) 

df_new = pd.concat([df.loc[ids_1, :].reset_index(), df.loc[ids_2, :].reset_index()], 1).drop('index', 1) 

df_new 

    id value id value 
0 1  a 2  b 
1 1  a 3  c 
2 2  b 1  a 
3 2  b 3  c 
4 3  c 1  a 
5 3  c 2  b 

有没有更简单的方法?

回答

5

我们想要得到方阵的上下三角形的索引。或者换句话说,在单位矩阵是零

np.eye(len(df)) 

array([[ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.]]) 

所以我从1

array([[ 0., 1., 1.], 
     [ 1., 0., 1.], 
     [ 1., 1., 0.]]) 

减去它在布尔上下文,并传递给np.where我得到完全的上部和下部三角形索引。

i, j = np.where(1 - np.eye(len(df))) 
df.iloc[i].reset_index(drop=True).join(
    df.iloc[j].reset_index(drop=True), rsuffix='_2') 

    id value id_2 value_2 
0 1  a  2  b 
1 1  a  3  c 
2 2  b  1  a 
3 2  b  3  c 
4 3  c  1  a 
5 3  c  2  b 
+1

可爱。 np.eye究竟如何适应这里? –

+1

增加了一些颜色。 – piRSquared

+0

不错的解决方案〜 – Wen

1

这完全可以在熊猫来完成:

df.loc[:, 'key_col'] = 1 # create a join column that will give us the Cartesian Product 

(df.merge(df, on='key_col', suffixes=('', '_2')) 
.query('id != id_2') # filter out joins on the same row 
.drop('key_col', axis=1) 
.reset_index(drop=True)) 

或者,如果你不想不得不放弃虚拟列,你可以调用df.merge时临时创建它:

(df.merge(df, on=df.assign(key_col=1)['key_col'], suffixes=('', '_2')) 
.query('id != id_2') # filter out joins on the same row 
.reset_index(drop=True)) 
+1

一个有趣的解决方案。但我想知道为合并创建一个虚拟列...... –

2

我之前有过这个问题,这是我的解决方案..

import itertools 
import pandas as pd 
c = list(itertools.product(DF.id.tolist(), DF.id.tolist())) 
Dic=dict(zip(DF.id, DF.value)) 
df = pd.DataFrame(c , columns=['id', 'id_2']) 
df[['value','value_2']]=df.apply(lambda x:x.map(Dic)) 
df.loc[df.id!=df.id_2,:] 


Out[125]: 
    id id_2 value value_2 
1 1  2  a  b 
2 1  3  a  c 
3 2  1  b  a 
5 2  3  b  c 
6 3  1  c  a 
7 3  2  c  b