首页 > 解决方案 > 在多列上使用 Pandas df.where 会产生意外的 NaN 值

问题描述

给定数据框

import pandas as pd

df = pd.DataFrame({
    'transformed': ['left', 'right', 'left', 'right'],
    'left_f': [1, 2, 3, 4],
    'right_f': [10, 20, 30, 40],
    'left_t': [-1, -2, -3, -4],
    'right_t': [-10, -20, -30, -40],
})

我想创建两个新列,从中选择left_*right_*根据以下内容进行选择transformed

df['transformed_f'] = df['right_f'].where(
    df['transformed'] == 'right',
    df['left_f']
)

df['transformed_t'] = df['right_t'].where(
    df['transformed'] == 'right',
    df['left_t']
)

我得到了预期的结果

df
#    transformed  left_f  right_f  left_t  right_t  transformed_f  transformed_t
# 0  left              1       10      -1      -10              1             -1
# 1  right             2       20      -2      -20             20            -20
# 2  left              3       30      -3      -30              3             -3
# 3  right             4       40      -4      -40             40            -40

但是,当我尝试在一个操作中执行此操作时,我得到一个包含NaN值的意外结果

df[['transformed_f', 'transformed_t']] = df[['right_f', 'right_t']].where(
    df['transformed'] == 'right',
    df[['left_f', 'left_t']]
)

df
#    transformed  left_f  right_f  left_t  right_t  transformed_f  transformed_t
# 0  left              1       10      -1      -10            NaN            NaN
# 1  right             2       20      -2      -20           20.0          -20.0
# 2  left              3       30      -3      -30            NaN            NaN
# 3  right             4       40      -4      -40           40.0          -40.0

有没有办法df.where()一次在多个列上使用?

标签: pythonpandas

解决方案


你很接近,只需添加.values.to_numpy()切片使其成为NDarray

根据文档:

other:标量、NDFrame 或 cond 为 False 的可调用条目被替换为来自 other 的相应值。如果 other 是可调用的,则在 NDFrame 上计算并应返回标量或 NDFrame。可调用对象不得更改输入 NDFrame(尽管 pandas 不会检查它)。

因此,当您直接输入数据帧的切片时,索引(列名称)不匹配,因此它不会更新 df,当您通过时.values,它会忽略索引并添加值。

df[['transformed_f', 'transformed_t']]=(df[['right_f', 'right_t']].
                        where(df['transformed'] == 'right',df[['left_f', 'left_t']].values))
print(df)

  transformed  left_f  right_f  left_t  right_t  transformed_f  transformed_t
0        left       1       10      -1      -10              1             -1
1       right       2       20      -2      -20             20            -20
2        left       3       30      -3      -30              3             -3
3       right       4       40      -4      -40             40            -40

推荐阅读