根据从另一行中选择的行和列,部分更新数据框

时间:2019-08-12 13:22:43

标签: python pandas dataframe

我有两个数据框,如下所示:

df1

Name    Id   c1  c2  c3  c4
---------------------------
asd     101  a   b   c   d
cdf     231  e   ?   1  
zxs     342  f   o      
ygg     521  g   k   p  
mlk     432  h   m       z
abc     343  c   x   q  
xyz     254  1   d   2  
fgg     165  c   z   d   mm
mnd     766  2   d   v  

df2

df2_Name    df2_Id  df2_c2  df2_c4
----------------------------------
asd          101      h      d2
ygg          521      x      cd
fgg          165      o      cm

我想将df1中的“名称”和“ id”与df2中的“ df2_Name”和“ df2_id”进行匹配。只要找到匹配项,df1中的“ c2”和“ c4”的值就会被df2中的“ df2_c2”和“ df2_c4”的值替换。

所需的输出

Name    Id    c1    c2  c3  c4
-------------------------------
asd     101    a    h   c   d2
cdf     231    e    ?   1   
zxs     342    f    o       
ygg     521    g    x   p   cd
mlk     432    h    m       z
abc     343    c    x   q   
xyz     254    1    d   2   
fgg     165    c    o   d   cm
mnd     766    2    d   v   

尝试解决方案1 ​​

df1[df1.set_index(['Name', 'id']).index.isin(df2.set_index(['df2_Name','df2_id']).index)].iloc[:,[3,5]].update(df2.iloc[:,[2,3]]) 

结果:按原样返回原始df1。

尝试解决方案2

df1.loc[df1.set_index(['Name', 'id']).index.isin(df2.set_index(['df2_Name','df2_id']).index), ['c2', 'c4']] = df2[['df2_c2', 'df2_c4']]

结果:引入了NaNs

Name    id   c1 c2  c3  c4
----------------------------
asd     101  a  NaN c   NaN
cdf     231  e  ?   1   
zxs     342  f  o       
ygg     521  g  NaN p   NaN
mlk     432  h  m       z
abc     343  c  x   q   
xyz     254  1  d   2   
fgg     165  c  NaN d   NaN
mnd     766  2  d   v   

尝试过的解决方案3 (仅适用于c2)

merged = df1.merge(df2, left_on=["id", "Name"], right_on=["df2_id", "df2_Name"])

merged["c2"] = merged.apply(lambda x: x["c2"] if pd.isnull(x["df2_c2"]) else x["df2_c2"], axis=1)

结果:

Name    id    c1 c2 c3  c4  df2_Name    df2_id  df2_c2  df2_c4
--------------------------------------------------------------
asd     101   a   h c   d   asd         101      h       d2
ygg     521   g   x p       ygg         521      x       cd
fgg     165   c   o d   mm  fgg         165      o       cm

此解决方案3替换了选定列的值,但是它返回了合并的数据帧,而不是带有更新的整个df1。

有人可以帮助我解决这个问题吗?

注意:

尝试以下解决方案后会询问此问题,但是没有成功:

  1. update-a-pandas-dataframe-with-data-from-another-dataframe
  2. replace-column-values-based-on-another-dataframe-python-pandas-better-way

1 个答案:

答案 0 :(得分:1)

我将使用merge来连接两个数据框。然后,您得到具有旧值的列和具有新值和nan值的列。然后使用apply来加入这些列:

merged = df1.merge(df2, how='outer', left_on=["id", "name"], right_on=["df2_id", "df2_name"])
merged["c2"] = merged.apply(lambda x: x["c2"] if pd.isnull(x["df2_c2"]) else x["df2_c2"], axis=1)
# Same for c4
# Drop df2_c2 and df2_c4

我目前无法对其进行测试,所以请告诉我这是否适合您。