Python Pandas基于多个值字段合并两个数据帧

时间:2015-03-28 08:01:03

标签: python pandas merge

我有两个Pandas的数据框

df1
       items        view
0      A|B|C  02-10-2015
1        D|E  02-15-2015

df2
  item  num  val
0    A    1   10
1    B    3    2
2    C    8    9
3    D    9   13
4    E    2   22

我想仅仅获得这些框架

df 
  view       num1 val1 num2 val2 num3 val3
0 02-10-2015 1    10   3    2    8    9
1 02-15-2015 9    13   2    22   na   na

我目前的做法是使用

拆分df1.items
df3 = pd.DataFrame(df1['items'].str.split('|').tolist())

导致

    0    1    2
0   A    B    C
1   D    E None

最后合并每个单独的列并将它们与原始df1

连接起来
x = pd.merge(df3[[0]], df2, how='left', on='item')
y = pd.merge(df3[[1]], df2, how='left', on='item')
z = pd.merge(df3[[2]], df2, how='left', on='item')
pd.concat([df1, x.ix[:,1:],y.ix[:,1:],z.ix[:,1:]], axis=1)

代码有效,但对我来说似乎不对,如果有人能够指出实现相同结果的正确方法,我会很高兴。

提前谢谢!

1 个答案:

答案 0 :(得分:4)

注意:str.split有一个return_type参数:

In [11]: res = df1['items'].str.split("|", return_type='frame')

In [12]: res
Out[12]:
   0  1    2
0  A  B    C
1  D  E  NaN

In [13]: res.index = df1['view']

In [14]: res
Out[14]:
            0  1    2
view
02-10-2015  A  B    C
02-15-2015  D  E  NaN

我认为更好,更通用的方法是使用stack / unstack:

In [15]: res = res.stack()

In [16]: res
Out[16]:
view
02-10-2015  0    A
            1    B
            2    C
02-15-2015  0    D
            1    E
dtype: object

现在你可以合并,或者如果你很幸运,只需转出索引:

In [17]: df2 = df2.set_index('item') # could just drop this column

In [18]: df2.loc[res]  # reorder, may not be required
Out[18]:
      num  val
item
A       1   10
B       3    2
C       8    9
D       9   13
E       2   22

现在魔术:

In [21]: df2.index = r.index

In [22]: df2
Out[22]:
              num  val
view
02-10-2015 0    1   10
           1    3    2
           2    8    9
02-15-2015 0    9   13
           1    2   22

In [23]: df2.unstack()
Out[23]:
           num        val
             0  1   2   0   1   2
view
02-10-2015   1  3   8  10   2   9
02-15-2015   9  2 NaN  13  22 NaN

根据需要(使用MultiIndex列,这是你想要的)。


注意:如果您有重复项(A,B,Cs),您将需要合并(这有点小,但可以清理)。在[21]之前:

In [31]: df2.merge(res.to_frame(), left_index=True, right_on=0).unstack()
Out[31]:
           num        val          0
             0  1   2   0   1   2  0  1    2
view
02-10-2015   1  3   8  10   2   9  A  B    C
02-15-2015   9  2 NaN  13  22 NaN  D  E  NaN