Pandas的部分合并

时间:2013-12-04 14:32:51

标签: python merge pandas

我在Pandas中使用重叠列合并2个不同大小的DataFrame时遇到了一些麻烦。

df1 =

+-------+--------+--------+-------+
| value | method | number | price |
+-------+--------+--------+-------+
| 0.5   | add    | 489245 | 600   |
| 0.7   | add    | 489245 | NaN   |
| 0.7   | mul    | 584682 | 225   |
| 0.9   | mul    | 624602 | NaN   |
| 0.95  | mul    | 624602 | NaN   |
| 0.99  | mul    | 624602 | NaN   |
| NaN   | NaN    | 900000 | 300   |
| NaN   | add    | 900000 | NaN   |
+-------+--------+--------+-------+

df2 =

+--------+-------+-----+-----+
| number | price | loc | get |
+--------+-------+-----+-----+
| 489245 | 200   | aa  | up  |
| 584682 | NaN   | ab  | NaN |
| 624602 | NaN   | bb  | NaN |
| 900000 | NaN   | cc  | dn  |
+--------+-------+-----+-----+

我预期的结果:

+-------+--------+--------+-------+-----+-----+
| value | method | number | price | loc | get |
+-------+--------+--------+-------+-----+-----+
| 0.5   | add    | 489245 | 200   | aa  | up  |
| 0.7   | add    | 489245 | 200   | aa  | up  |
| 0.7   | mul    | 584682 | 225   | ab  | NaN |
| 0.9   | mul    | 624602 | NaN   | bb  | NaN |
| 0.95  | mul    | 624602 | NaN   | bb  | NaN |
| 0.99  | mul    | 624602 | NaN   | bb  | NaN |
| NaN   | NaN    | 900000 | 300   | cc  | dn  |
| NaN   | add    | 900000 | NaN   | cc  | dn  |
+-------+--------+--------+-------+-----+-----+

例如,要加入的列='数字'。如果df1和df2在重叠列上都具有非NaN值(如'price'),则df2将是优选的。否则,应该写一个非NaN的人。

2 个答案:

答案 0 :(得分:3)

摘要:merge后跟一些DataFrame操作,然后是update

首先加载数据(此处包含以供参考)。

In [1]: import pandas
In [2]: df1 = pandas.read_csv('df1.csv')
In [3]: df2 = pandas.read_csv('df2.csv')
In [4]: df1
Out[4]: 
   value method  number  price
0   0.50    add  489245    600
1   0.70    add  489245    NaN
2   0.70    mul  584682    225
3   0.90    mul  624602    NaN
4   0.95    mul  624602    NaN
5   0.99    mul  624602    NaN
6    NaN    NaN  900000    300
7    NaN    add  900000    NaN
8    NaN    NaN     NaN    NaN

In [5]: df2
Out[5]: 
   number  price loc  get
0  489245    200  aa  up 
1  584682    NaN  ab  NaN
2  624602    NaN  bb  NaN
3  900000    NaN  cc  dn 

接下来合并'number'

上的两个数据框
In [6]: mdf = pandas.merge(df1,df2,on='number')
In [7]: mdf
Out[7]: 
   value method  number  price_x  price_y loc  get
0   0.50    add  489245      600      200  aa  up 
1   0.70    add  489245      NaN      200  aa  up 
2   0.70    mul  584682      225      NaN  ab  NaN
3   0.90    mul  624602      NaN      NaN  bb  NaN
4   0.95    mul  624602      NaN      NaN  bb  NaN
5   0.99    mul  624602      NaN      NaN  bb  NaN
6    NaN    NaN  900000      300      NaN  cc  dn 
7    NaN    add  900000      NaN      NaN  cc  dn 

当显示相同的列时,pandas.merge会将两者都放在合并的DataFrame中,并附加后缀。在这种情况下,我们希望使用'price_x'更新'price_y'并调用结果'price'。为此,我们可以创建一个仅包含'price_y'中数据的数据框,从合并的DataFrame中删除该列,并将价格列重命名为'price'

In [8]: pdf = mdf.price_y
In [9]: pdf = pandas.DataFrame(pdf)

In [10]: del mdf['price_y']

In [11]: mdf.rename(columns = {'price_x':'price'},inplace=True)
In [12]: pdf.rename(columns = {'price_y':'price'},inplace=True)
In [13]: mdf
Out[13]: 
   value method  number  price loc  get
0   0.50    add  489245    600  aa  up 
1   0.70    add  489245    NaN  aa  up 
2   0.70    mul  584682    225  ab  NaN
3   0.90    mul  624602    NaN  bb  NaN
4   0.95    mul  624602    NaN  bb  NaN
5   0.99    mul  624602    NaN  bb  NaN
6    NaN    NaN  900000    300  cc  dn 
7    NaN    add  900000    NaN  cc  dn 

In [14]: pdf
Out[14]: 
   price
0    200
1    200
2    NaN
3    NaN
4    NaN
5    NaN
6    NaN
7    NaN

现在我们可以使用.updatepdf中的任何非NaN值放入mdf

In [15]: mdf.update(pdf)

In [16]: mdf
Out[16]: 
   value method  number  price loc  get
0   0.50    add  489245    200  aa  up 
1   0.70    add  489245    200  aa  up 
2   0.70    mul  584682    225  ab  NaN
3   0.90    mul  624602    NaN  bb  NaN
4   0.95    mul  624602    NaN  bb  NaN
5   0.99    mul  624602    NaN  bb  NaN
6    NaN    NaN  900000    300  cc  dn 
7    NaN    add  900000    NaN  cc  dn 

如果需要更复杂的规则选择值,请将mdf.update(pdf)替换为mdf.combine(pdf, function_of_two_variables_returning_preferred_value)

答案 1 :(得分:2)

合并后可以使用numpy.where()

>>> df1 = pd.DataFrame({'number':[1,1,2,2,3], 'price':[600,np.NaN,225,np.NaN,np.NaN], 'method':['add','add','mul','mul','mul']})
>>> df2 = pd.DataFrame({'number':[1,2,3], 'price':[200,np.NaN,np.NaN], 'loc':['aa','bb','cc']})
>>> df3 = pd.merge(df1, df2, on='number', suffixes=['_1', ''])
>>> df3
  method  number  price_1 loc    price
0    add       1      600  aa      200
1    add       1      NaN  aa      200
2    mul       2      225  bb      NaN
3    mul       2      NaN  bb      NaN
4    mul       3      NaN  cc      NaN

>>> df3['price'] = np.where(df3['price'].isnull(), df3['price_1'], df3['price'])
>>> df3
  method  number  price_1 loc  price
0    add       1      600  aa    200
1    add       1      NaN  aa    200
2    mul       2      225  bb    225
3    mul       2      NaN  bb    NaN
4    mul       3      NaN  cc    NaN
>>> del df3['price_1']
>>> df3
  method  number loc  price
0    add       1  aa    200
1    add       1  aa    200
2    mul       2  bb    225
3    mul       2  bb    NaN
4    mul       3  cc    NaN

另一种方法是使用pandas.Series.fillna()方法:

>>> df3['price'] = df3['price'].fillna(df3['price_1'])
>>> del df3['price_1']
>>> df3
  method  number loc  price
0    add       1  aa    200
1    add       1  aa    200
2    mul       2  bb    225
3    mul       2  bb    NaN
4    mul       3  cc    NaN