在多列上使用Pandas df.where会产生意外的NaN值

时间:2019-06-27 12:56:33

标签: python pandas

给出数据框

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()

1 个答案:

答案 0 :(得分:4)

您接近了,只需在切片中添加.values.to_numpy()使其成为NDarray

每个文档:

  

other:标量,NDFrame或可调用   cond为False的条目将替换为其他条目的对应值。如果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