嵌套np.where

时间:2019-01-16 12:46:41

标签: python pandas numpy

我有以下数据框:

S A
1 1
1 0
2 1
2 0

我想创建一个新的'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))))

但是当我执行它时,出现以下错误:

SyntaxError: invalid syntax

我的代码有什么问题?

3 个答案:

答案 0 :(得分:1)

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

如果重写np.where,则只能使用两个结果,并且当条件不为True时,将始终设置第二个结果。因此,还将为(S == 5) & (A = np.nan)之类的值进行设置。

df['Result'] = np.where(((df.S == 1) & (df.A == 1)) | ((df.S == 2) & (df.A == 0)), 1, 0)

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

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

在不满足任何条件的情况下,结果将设置为np.nan。这是不安全的,因此应使用。但是,如果您想在这些位置使用零,只需用零初始化Results列即可。
当然,对于特殊情况(例如仅包含1和0的情况)可以简化此操作,而通过使用dict或其他容器将其扩展为任意数量的结果。

答案 1 :(得分:1)

您应该使用嵌套的np.where。就像sql case子句。但是,当数据中存在nan时要小心。

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

输出:

|   | S | A | Result |
|---|---|---|--------|
| 0 | 1 | 1 | 1      |
| 1 | 1 | 0 | 0      |
| 2 | 2 | 1 | 0      |
| 3 | 2 | 0 | 1      |

答案 2 :(得分:0)

如果您有非常嵌套的操作,我建议您使用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])