合并两列,同时优先考虑第一列

时间:2019-01-04 05:20:55

标签: python pandas dataframe merge nan

this question中,我有两个矩阵,并且希望将它们合并,以使我可以将dfB合并到dfA上,无论我在哪里拥有NaN值,都可以用非NaN值替换。

>>> dfA
  s_name  geo    zip  date value
0      A  zip  60601  2010   NaN  # In the earlier question, this was None
1      B  zip  60601  2010   NaN  # rather than NaN, which was
2      C  zip  60601  2010   NaN  # a mistake.
3      D  zip  60601  2010   NaN

>>> dfB
  s_name  geo    zip  date  value
0      A  zip  60601  2010    1.0
1      B  zip  60601  2010    NaN
3      D  zip  60601  2010    4.0

合并它们,我看到了:

>>> new = pd.merge(dfA,dfB,on=["s_name","geo", "geoid", "date"],how="left")
>>> new.head()
  name    geo   zip  date  value_x  value_y
0    A  state    01  2009      NaN      1.0
1    B  state    01  2010      NaN      NaN
2    C  state    01  2011      NaN      NaN
3    D  state    01  2012      NaN      4.0
4    E  state    01  2013      NaN      5.0

我不能确定value_y总是被编号而value_x总是NaN。但是我想要一个合并的值,将其称为value,即无论哪个值都不是NaN。我试试这个:

>>> new["value"] = new.apply(lambda r: r.value_x or r.value_y, axis=1)
>>> new.head()
  name    geo   zip  date  value_x  value_y  value
0    A  state    01  2009      NaN      1.0    NaN
1    B  state    01  2010      NaN      NaN    NaN
2    C  state    01  2011      NaN      NaN    NaN
3    D  state    01  2012      NaN      4.0    NaN
4    E  state    01  2013      NaN      5.0    NaN

哦,不。

有意义的是NaN应该传播,但这不是我想要的。我想要的逻辑将返回存在的任何一个,如果存在则不返回NaN。

我希望没有人给我的逻辑。您可以看到:

>>> new["value_z"] = None
>>> new.head()
  name    geo   zip  date  value_x  value_y  value value_z
0    A  state    01  2009      NaN      1.0    NaN    None
1    B  state    01  2010      NaN      NaN    NaN    None
2    C  state    01  2011      NaN      NaN    NaN    None
3    D  state    01  2012      NaN      4.0    NaN    None
4    E  state    01  2013      NaN      5.0    NaN    None

>>> new["value2"] = new.apply(lambda r: r.value_z or r.value_y, axis=1)
>>> new.head()
  name    geo   zip  date  value_x  value_y  value value_z   value2
0    A  state    01  2009      NaN      1.0    NaN    None      1.0
1    B  state    01  2010      NaN      NaN    NaN    None      NaN
2    C  state    01  2011      NaN      NaN    NaN    None      NaN
3    D  state    01  2012      NaN      4.0    NaN    None      4.0
4    E  state    01  2013      NaN      5.0    NaN    None      5.0

创建value2的逻辑是我正在寻找的行为,而不是value

执行此操作的最佳方法是什么?

3 个答案:

答案 0 :(得分:5)

如果您偏爱value_x,则可以尝试:

df.value_x = df.value_x.fillna(df.value_y)
df.pop('value_y')

或:

df.value_x=df.value_x.fillna(df.pop('value_y'))

>>df
   name geo    zip  date    value_x
0   A   state   1   2009    1.0
1   B   state   1   2010    NaN
2   C   state   1   2011    NaN
3   D   state   1   2012    4.0
4   E   state   1   2013    5.0

答案 1 :(得分:3)

combine_first将在merge之后生效:

dfC = pd.merge(dfA, dfB, on=["s_name", "geo", "zip", "date"], how="left")
dfC['value'] = dfC.pop('value_x').combine_first(dfC.pop('value_y'))
dfC

  s_name  geo    zip  date  value
0      A  zip  60601  2010    1.0
1      B  zip  60601  2010    NaN
2      C  zip  60601  2010    NaN
3      D  zip  60601  2010    4.0

combine_first优先于“ value_x”而不是“ value_y”。您也可以这样写:

dfC = pd.merge(dfA, dfB, on=["s_name", "geo", "zip", "date"], how="left")
dfC['value_x'] = dfC['value_x'].combine_first(dfC.pop('value_y'))
dfC

  s_name  geo    zip  date  value_x
0      A  zip  60601  2010      1.0
1      B  zip  60601  2010      NaN
2      C  zip  60601  2010      NaN
3      D  zip  60601  2010      4.0

答案 2 :(得分:0)

从技术上讲,这是通过敲定逻辑来实现的,但它很丑陋,感觉就像是骇客(我相信由于操作员短路,它偏爱value_x吗?):

>>> new["value3"] = new.apply(lambda r: (not(pd.isna(r.value_x)) or r.value_y) or (r.value_x or not(pd.isna(r.value_y))), axis=1)

>>> new.head()
  name    geo   zip  date  value_x  value_y  value value_z   value2 value3
0    A  state    01  2009      NaN      1.0    NaN    None      1.0    1.0
1    B  state    01  2010      NaN      NaN    NaN    None      NaN    NaN
2    C  state    01  2011      NaN      NaN    NaN    None      NaN    NaN
3    D  state    01  2012      NaN      4.0    NaN    None      4.0    4.0
4    E  state    01  2013      NaN      5.0    NaN    None      5.0    5.0