np.where 有多个条件
np.where with multiple conditions
我有以下示例数据框。
A B C D
1 0 0 0
2 0 0 1
3 1 1 0
4 0 0 1
5 -1 1 1
6 0 0 1
7 0 1 0
8 1 1 1
9 0 0 0
10 -1 0 0
我需要根据以下规则填写D列。
1)我手动将D的第一个值赋为0
df.loc[[0], 'D'] = 0
2) 我需要根据以下条件填写 df['D'] 的其余行。
IF
A = 1 AND B = 1 AND D.SHIFT(1) = 0, THEN D = 1
ELSE IF
A = 0, THEN D = D.SHIFT(1)
ELSE IF
A = -1 AND C = 1 AND D.SHIFT(1) = 0, THEN D = -1
ELSE
D = 0
以下是我的代码。
import numpy as np
import pandas as pd
df = pd.DataFrame([[0, 0, 0]]*10, columns=list('ABC'), index=range(1, 11))
df.loc[[3, 8], 'A'] = 1
df.loc[[5, 10], 'A'] = -1
df.loc[[3, 5, 7, 8], 'B'] = 1
df.loc[[2, 4, 5, 6, 8], 'C'] = 1
df.loc[[1], 'D'] = 0
df['D'] = np.where((df.A == 1) & (df.B == 1) & (df.D.shift(1) == 0), 1,
np.where((df.A == 0) , df.D.shift(1),
np.where((df.A == -1) & (df.C == 1) & (df.D.shift(1) == 0), -1, 0)))
print(df)
预期输出是
A B C D
1 0 0 0 0
2 0 0 1 0
3 1 1 0 1
4 0 0 1 1
5 -1 1 1 0
6 0 0 1 0
7 0 1 0 0
8 1 1 1 1
9 0 0 0 1
10 -1 0 0 0
但我收到的实际输出如下,这不是我想要的输出。
A B C D
1 0 0 0 NaN
2 0 0 1 0.0
3 1 1 0 0.0
4 0 0 1 NaN
5 -1 1 1 0.0
6 0 0 1 NaN
7 0 1 0 NaN
8 1 1 1 0.0
9 0 0 0 NaN
10 -1 0 0 0.0
非常感谢任何帮助。
编辑:我分配第一行 df['D'] = 0 的原因是,df['D'] 也依赖于 df['D']。转移(1)。如果有任何其他方法可以做到这一点,即使没有分配 df['D'] 的第一个值,我也很好。
定义以下函数:
def fn(row):
if fn.prevD is None:
fn.prevD = 0
elif (row.A == 1) & (row.B == 1) & (fn.prevD == 0):
fn.prevD = 1
elif row.A == 0:
pass
elif (row.A == -1) & (row.C == 1) & (fn.prevD == 0):
fn.prevD = -1
else:
fn.prevD = 0
return fn.prevD
然后应用它:
fn.prevD = None
df['D'] = df.apply(fn, axis=1)
我有以下示例数据框。
A B C D
1 0 0 0
2 0 0 1
3 1 1 0
4 0 0 1
5 -1 1 1
6 0 0 1
7 0 1 0
8 1 1 1
9 0 0 0
10 -1 0 0
我需要根据以下规则填写D列。
1)我手动将D的第一个值赋为0
df.loc[[0], 'D'] = 0
2) 我需要根据以下条件填写 df['D'] 的其余行。
IF
A = 1 AND B = 1 AND D.SHIFT(1) = 0, THEN D = 1
ELSE IF
A = 0, THEN D = D.SHIFT(1)
ELSE IF
A = -1 AND C = 1 AND D.SHIFT(1) = 0, THEN D = -1
ELSE
D = 0
以下是我的代码。
import numpy as np
import pandas as pd
df = pd.DataFrame([[0, 0, 0]]*10, columns=list('ABC'), index=range(1, 11))
df.loc[[3, 8], 'A'] = 1
df.loc[[5, 10], 'A'] = -1
df.loc[[3, 5, 7, 8], 'B'] = 1
df.loc[[2, 4, 5, 6, 8], 'C'] = 1
df.loc[[1], 'D'] = 0
df['D'] = np.where((df.A == 1) & (df.B == 1) & (df.D.shift(1) == 0), 1,
np.where((df.A == 0) , df.D.shift(1),
np.where((df.A == -1) & (df.C == 1) & (df.D.shift(1) == 0), -1, 0)))
print(df)
预期输出是
A B C D
1 0 0 0 0
2 0 0 1 0
3 1 1 0 1
4 0 0 1 1
5 -1 1 1 0
6 0 0 1 0
7 0 1 0 0
8 1 1 1 1
9 0 0 0 1
10 -1 0 0 0
但我收到的实际输出如下,这不是我想要的输出。
A B C D
1 0 0 0 NaN
2 0 0 1 0.0
3 1 1 0 0.0
4 0 0 1 NaN
5 -1 1 1 0.0
6 0 0 1 NaN
7 0 1 0 NaN
8 1 1 1 0.0
9 0 0 0 NaN
10 -1 0 0 0.0
非常感谢任何帮助。
编辑:我分配第一行 df['D'] = 0 的原因是,df['D'] 也依赖于 df['D']。转移(1)。如果有任何其他方法可以做到这一点,即使没有分配 df['D'] 的第一个值,我也很好。
定义以下函数:
def fn(row):
if fn.prevD is None:
fn.prevD = 0
elif (row.A == 1) & (row.B == 1) & (fn.prevD == 0):
fn.prevD = 1
elif row.A == 0:
pass
elif (row.A == -1) & (row.C == 1) & (fn.prevD == 0):
fn.prevD = -1
else:
fn.prevD = 0
return fn.prevD
然后应用它:
fn.prevD = None
df['D'] = df.apply(fn, axis=1)