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

Nil*_*ner 6 python pandas

给定DataFrame

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],
})
Run Code Online (Sandbox Code Playgroud)

我想创建两个新列,从中选择一个,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']
)
Run Code Online (Sandbox Code Playgroud)

我得到了预期的结果

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
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试在一个操作中执行此操作时,会得到包含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
Run Code Online (Sandbox Code Playgroud)

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

ank*_*_91 5

您很接近,只需添加.valuesor.to_numpy()与切片即可使其成为NDarray

\n\n

根据文档:

\n\n
\n

other :标量、NDFrame 或可调用\n cond 为 False 的条目将替换为 other 中的相应值。如果 other 可调用,则在 NDFrame 上计算并应返回标量或 NDFrame。可调用不得更改输入 NDFrame (尽管 pandas 不会检查它\xe2\x80\x99t)。

\n
\n\n

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

\n\n
df[['transformed_f', 'transformed_t']]=(df[['right_f', 'right_t']].\n                        where(df['transformed'] == 'right',df[['left_f', 'left_t']].values))\nprint(df)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n
  transformed  left_f  right_f  left_t  right_t  transformed_f  transformed_t\n0        left       1       10      -1      -10              1             -1\n1       right       2       20      -2      -20             20            -20\n2        left       3       30      -3      -30              3             -3\n3       right       4       40      -4      -40             40            -40\n
Run Code Online (Sandbox Code Playgroud)\n