嵌套 np.where

MoM*_*oMo 3 python numpy pandas

我有以下数据框:

S A
1 1
1 0
2 1
2 0
Run Code Online (Sandbox Code Playgroud)

我想创建一个'Result'基于 A 列和 S 列的值计算的新列。

我写了以下嵌套np.where代码

df['Result'] = np.where((df.S == 1 & df.A == 1), 1,
                        (df.S == 1 & df.A == 0), 0,
                        (df.S == 2 & df.A == 1), 0,
                        (df.S == 2 & df.A == 0), 1))))
Run Code Online (Sandbox Code Playgroud)

但是当我执行它时,我收到以下错误:

SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

我的代码有什么问题?

dbo*_*ers 9

如果您有非常嵌套的操作,我建议使用numpy.select 。

df = pd.DataFrame({
    "S": [1, 1, 2, 2],
    "A": [1, 0, 1, 0]
})

# you could of course combine the clause (1, 4) and (2, 3) with the '|' or operator
df['RESULT'] = np.select([
    (df.S == 1) & (df.A == 1),
    (df.S == 1) & (df.A == 0),
    (df.S == 2) & (df.A == 1),
    (df.S == 2) & (df.A == 0)
], [1, 0, 0, 1])
Run Code Online (Sandbox Code Playgroud)


Sco*_*y1- 8

据我所知np.where不支持多条return语句(至少不超过两条)。因此,要么您重写您np.where的结果以生成一个 True 和一个 False 语句,并为 True/False 返回 1/0,要么您需要使用掩码。

如果你重写np.where,你只能得到两个结果,当条件不为真时,第二个结果将始终被设置。所以它也会被设置为像(S == 5) & (A = np.nan).

df['Result'] = np.where(((df.S == 1) & (df.A == 1)) | ((df.S == 2) & (df.A == 0)), 1, 0)
Run Code Online (Sandbox Code Playgroud)

使用掩码时,您可以应用任意数量的条件和结果。对于您的示例,解决方案如下所示:

mask_0 = ((df.S == 1) & (df.A == 0)) | ((df.S == 2) & (df.A == 1))
mask_1 = ((df.S == 1) & (df.A == 1)) | ((df.S == 2) & (df.A == 0))
df.loc[mask_0, 'Result'] = 0
df.loc[mask_1, 'Result'] = 1
Run Code Online (Sandbox Code Playgroud)

结果将设置np.nan为不满足任何条件。这是 imho 故障安全,因此应该使用。但是如果你想在这些位置有零,只需Results用零初始化你的列。
当然,这可以在特殊情况下简化,例如只有 1 和 0 作为结果,并通过使用 dicts 或其他容器扩展为任意数量的结果。


Ben*_*018 6

You should use nested np.where. It is like sql case clause. But be careful when there is nan in the data.

df=pd.DataFrame({'S':[1,1,2,2],'A':[1,0,1,0]})
df['Result'] = np.where((df.S == 1) & (df.A == 1), 1,   #when... then
                 np.where((df.S == 1) & (df.A == 0), 0,  #when... then
                  np.where((df.S == 2) & (df.A == 1), 0,  #when... then
                    1)))                                  #else
df
Run Code Online (Sandbox Code Playgroud)

output:

|   | S | A | Result |
|---|---|---|--------|
| 0 | 1 | 1 | 1      |
| 1 | 1 | 0 | 0      |
| 2 | 2 | 1 | 0      |
| 3 | 2 | 0 | 1      |
Run Code Online (Sandbox Code Playgroud)