Pandas: 在条件之后创建指标列
Pandas: Creating indicator column after condition
import numpy as np
import pandas as pd
df = pd.DataFrame({
'cond': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B','B', 'B', 'B', 'B', 'B','B','B'],
'Array': ['S', 'S', 'TT', 'TT','S', 'S', 'TT', 'TT','S', 'S', 'TT', 'TT','S', 'S', 'TT', 'TT','SS','TT'],
'Area': [3.0, 2.0, 2.88, 1.33, 2.44, 1.25, 1.53, 1.0, 0.156, 2.0, 2.4, 6.3, 6.9, 9.78, 10.2, 3.0, 16.0, 19.0]
})
print(df)
我正在尝试制作一个指示器列,指示某个区域是否已经发生。因此,例如,如果条件。是A,那么我想第一次表明面积<=1.5(以及之后的所有数据点),如果条件。是 B,则表示第一次面积 >10(以及之后的所有点)。最终结果应如下所示:
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
我查看的许多其他示例是指示 A 的面积是否 <=1.5,或指示它第一次发生,但不指示它第一次发生并指示之后的所有数据点.这个想法是,一旦我的状况达到某个区域,它就会进入一个不同的“阶段”,我试图指出“A”何时进入并停留在该阶段(以及 B 的等效阶段)。
你可以写条件,然后按cond
分组,用cumsum
+ clip
:
mask = (df['cond'].eq('A') & df['Area'].lt(1.5)) | (df['cond'].eq('B') & df['Area'].gt(10))
df['Indicator'] = mask.groupby(df['cond']).cumsum().clip(0, 1)
输出:
>>> df
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
您可以通过将面积值与每个 cond
的截止点进行比较来创建布尔系列。要创建布尔系列,我们首先必须将截止点映射到 cond
s;并且由于 B 要求大于 check 而 A 要求小于 check;我们必须反转 B
的符号才能在同一方向上进行两个条件检查。
然后使用groupby.cummax
得到想要的指标:
mapping = {'A':1.5, 'B':-10}
area = df['Area'].mask(df['cond'].eq('B'), -df['Area'])
df['Indicator'] = df['cond'].map(mapping).ge(area).groupby(df['cond']).cummax().astype(int)
输出:
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
使用 expanding
查找之前的任何值是否符合您的条件:
condA = df["cond"].eq("A")&df["Area"].expanding().apply(lambda x: x.lt(1.5).any())
condB = df["cond"].eq("B")&df["Area"].expanding().apply(lambda x: x.gt(10).any())
df["Indicator"] = (condA|condB).astype(int)
>>> df
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
import numpy as np
import pandas as pd
df = pd.DataFrame({
'cond': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B','B', 'B', 'B', 'B', 'B','B','B'],
'Array': ['S', 'S', 'TT', 'TT','S', 'S', 'TT', 'TT','S', 'S', 'TT', 'TT','S', 'S', 'TT', 'TT','SS','TT'],
'Area': [3.0, 2.0, 2.88, 1.33, 2.44, 1.25, 1.53, 1.0, 0.156, 2.0, 2.4, 6.3, 6.9, 9.78, 10.2, 3.0, 16.0, 19.0]
})
print(df)
我正在尝试制作一个指示器列,指示某个区域是否已经发生。因此,例如,如果条件。是A,那么我想第一次表明面积<=1.5(以及之后的所有数据点),如果条件。是 B,则表示第一次面积 >10(以及之后的所有点)。最终结果应如下所示:
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
我查看的许多其他示例是指示 A 的面积是否 <=1.5,或指示它第一次发生,但不指示它第一次发生并指示之后的所有数据点.这个想法是,一旦我的状况达到某个区域,它就会进入一个不同的“阶段”,我试图指出“A”何时进入并停留在该阶段(以及 B 的等效阶段)。
你可以写条件,然后按cond
分组,用cumsum
+ clip
:
mask = (df['cond'].eq('A') & df['Area'].lt(1.5)) | (df['cond'].eq('B') & df['Area'].gt(10))
df['Indicator'] = mask.groupby(df['cond']).cumsum().clip(0, 1)
输出:
>>> df
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
您可以通过将面积值与每个 cond
的截止点进行比较来创建布尔系列。要创建布尔系列,我们首先必须将截止点映射到 cond
s;并且由于 B 要求大于 check 而 A 要求小于 check;我们必须反转 B
的符号才能在同一方向上进行两个条件检查。
然后使用groupby.cummax
得到想要的指标:
mapping = {'A':1.5, 'B':-10}
area = df['Area'].mask(df['cond'].eq('B'), -df['Area'])
df['Indicator'] = df['cond'].map(mapping).ge(area).groupby(df['cond']).cummax().astype(int)
输出:
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1
使用 expanding
查找之前的任何值是否符合您的条件:
condA = df["cond"].eq("A")&df["Area"].expanding().apply(lambda x: x.lt(1.5).any())
condB = df["cond"].eq("B")&df["Area"].expanding().apply(lambda x: x.gt(10).any())
df["Indicator"] = (condA|condB).astype(int)
>>> df
cond Array Area Indicator
0 A S 3.000 0
1 A S 2.000 0
2 A TT 2.880 0
3 A TT 1.330 1
4 A S 2.440 1
5 A S 1.250 1
6 A TT 1.530 1
7 A TT 1.000 1
8 A S 0.156 1
9 B S 2.000 0
10 B TT 2.400 0
11 B TT 6.300 0
12 B S 6.900 0
13 B S 9.780 0
14 B TT 10.200 1
15 B TT 3.000 1
16 B SS 16.000 1
17 B TT 19.000 1