在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
。
执行此操作的最佳方法是什么?
答案 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