大熊猫数据框的笛卡尔积与自身

时间:2017-07-31 23:40:41

标签: python pandas dataframe

给定数据框:

    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

有更简单的方法吗?

3 个答案:

答案 0 :(得分:6)

我们想要得到方形矩阵的上三角和下三角的索引。或者换言之,身份矩阵为零

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 :(得分:2)

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

SectionPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
ViewPager mViewPager = (ViewPager) findViewById(R.id.container);
CircularIndicatorTabLayout tabLayout = (CircularIndicatorTabLayout) findViewById(R.id.tab_monitoring_criteria);  
mViewPager.setAdapter(mSectionsPagerAdapter);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.setIcons(R.drawable.ic_arrow_drop_down, R.drawable.ic_audiotrack, R.drawable.ic_beach);

答案 2 :(得分: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))