【问题标题】:Partial merge in PandasPandas 中的部分合并
【发布时间】:2013-12-04 14:32:50
【问题描述】:

我在将 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  |
+-------+--------+--------+-------+-----+-----+

例如,要加入的列 = 'number'。如果 df1 和 df2 在重叠列上都有非 NaN 值(如“价格”),则 df2 将更可取。否则,应该写一个非 NaN 的。

【问题讨论】:

    标签: python merge pandas


    【解决方案1】:

    总结: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_y' 更新'price_x' 并调用结果'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)

    【讨论】:

      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 2019-12-21
        • 1970-01-01
        • 2019-09-12
        • 2021-03-13
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 2018-05-24
        • 2014-09-05
        相关资源
        最近更新 更多