Pandas基于条件交换列

15

我有一个如下所示的pandas数据框:

    Col1  Col2  Col3
0   A     7     NaN
1   B     16    NaN
1   B     16    15

我想做的是将Col3值为NaN的列与Col2交换。根据SO上的其他帖子和答案,我到目前为止有这段代码:

df[['Col2', 'Col3']] = df[['Col3', 'Col2']].where(df[['Col3']].isnull())

但是这似乎不能正常工作,并给我以下结果:

    Col1  Col2  Col3
0   A     NaN   NaN
1   B     NaN   NaN
1   B     NaN   NaN

我是否遗漏了什么重要的东西?

更新:我的期望输出如下:

    Col1  Col2  Col3
0   A     NaN   7
1   B     NaN   16
1   B     16    15

谢谢


当Col3为None时,您是指什么?如果所有元素都是NaN或仅一个元素就足够了吗? - ayhan
1
@ayhan 对于某些行,Col3的值为NaN,当发生这种情况时,我想将其与Col2交换。我编辑了问题,希望现在清楚了。 - dagg3r
2个回答

17

你可以使用 loc 进行交换:

df.loc[df['Col3'].isnull(), ['Col2', 'Col3']] = df.loc[df['Col3'].isnull(), ['Col3', 'Col2']].values
注意,.values是必需的,以确保交换正确完成,否则Pandas将尝试根据索引和列名进行对齐,并且不会发生交换。
如果您认为代码更清晰,您也可以单独重新分配每行:
null_idx = df['Col3'].isnull()
df.loc[null_idx, 'Col3'] = df['Col2']
df.loc[null_idx, 'Col2'] = np.nan

生成的输出:

  Col1  Col2  Col3
0    A   NaN   7.0
1    B   NaN  16.0
2    B  16.0  15.0

11

试一下这个:(它更快)

df["Col3"], df["Col2"] = np.where(df['Col3'].isnull(), [df["Col2"], df["Col3"]], [df["Col3"], df["Col2"] ])
df

     Col1  Col2  Col3
0    A   NaN   7.0
1    B   NaN  16.0
1    B  16.0  15.0


    %timeit df.loc[df['Col3'].isnull(), ['Col2', 'Col3']] = df.loc[df['Col3'].isnull(), ['Col3', 'Col2']].values
100 loops, best of 3: 2.68 ms per loop


    %timeit df["Col3"], df["Col2"] = np.where(df['Col3'].isnull(), [df["Col2"], df["Col3"]], [df["Col3"], df["Col2"] ])
1000 loops, best of 3: 592 µs per loop

谢谢你,梅林。你有什么想法,为什么这种方法比另一种更快吗? - dagg3r
我知道,我在想是什么原因导致了加速。并且我也已经给你的答案点赞了。 - dagg3r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接