在另一列中的两个条目之间查找列的最小值
Finding minimum value of a column between two entries in another column
浏览了 64 次
0
我在包含超过 1000 行的数据框中有两列。 A 列可以取值 X、Y、None。 B 列包含从 50 到 100 的随机数。
每次在A列中出现非'None'次,就认为是第4次出现。因此,A 列中上一个非 None 事件将是 occurrence3,之前的事件将是 occurrence2,之前的事件将是 occurrence1。我想找到 occurrence4 和 occurrence3 之间的 B 列的最小值,并检查它是否大于 occurrence2 和 occurrence1 之间的 B 列的最小值。结果可以作为 "YES" 或 "NO".
存储在数据框中的新列中
样本输入
ROWNUM A B
1 None 68
2 None 83
3 X 51
4 None 66
5 None 90
6 Y 81
7 None 81
8 None 100
9 None 83
10 None 78
11 X 68
12 None 53
13 None 83
14 Y 68
15 None 94
16 None 50
17 None 71
18 None 71
19 None 52
20 None 67
21 None 82
22 X 76
23 None 66
24 None 92
例如,我需要找到 B 列在 ROWNUM 14 和 ROWNUM 11 之间的最小值,并检查它是否大于 B 列在 ROWNUM 6 和 ROWNUM 3 之间的最小值。接下来,我需要找到ROWNUM 22 和 ROWNUM 14 之间的最小值,并检查它是否大于 ROWNUM 11 和 ROWNNUM 6 之间的最小值,依此类推。
编辑:
在示例数据中,我们从第 14 行开始计算,因为这是我们第四次出现非 none 列 A。第 14 行和第 11 行之间的最小值为 53。第 6 行和第 3 行之间的最小值为 51。由于 53 > 51,这意味着 B 列在第 4 次和第 3 次之间的最小值大于第 2 次和第 1 次之间 B 列的最小值。因此,输出为第 14 行将是 "YES" 或 1.
接下来,在第22行,第22行和第14行之间的最小值为50。第11行和第6行之间的最小值为68。由于50 < 68,这意味着第4次出现和第3次出现之间的最小值不是大于第 2 次出现和第 1 次出现之间的最小值。因此,第 22 行的输出将为 "NO" 或 0。
我有以下代码。
import numpy as np
import pandas as pd
df = pd.DataFrame([[0, 0]]*100, columns=list('AB'), index=range(1, 101))
df.loc[[3, 6, 11, 14, 22, 26, 38, 51, 64, 69, 78, 90, 98], 'A'] = 1
df['B'] = np.random.randint(50, 100, size=len(df))
df['result'] = df.index[df['A'] != 0].to_series().rolling(4).apply(
lambda x: df.loc[x[2]:x[3], 'B'].min() > df.loc[x[0]:x[1], 'B'].min(), raw=True)
print(df)
当 A 列有输入 [0,1] 时,此代码有效。但是我需要一个代码,其中 A 列可以包含 [None, X, Y]。此外,此代码生成的输出为 [0,1]。我需要输出为 [YES, NO]。
这是我的方法:
def is_incr(x):
return x[:2].min() > x[2:].min()
# replace with s = df['A'] == 'None' if needed
s = df['A'].isna()
df['new_col'] = df.loc[s, 'B'].rolling(4).apply(is_incr)
输出:
ROWNUM A B new_col
0 1 NaN 68 NaN
1 2 NaN 83 NaN
2 3 X 51 NaN
3 4 NaN 66 NaN
4 5 NaN 90 1.0
5 6 Y 81 NaN
6 7 NaN 81 0.0
7 8 NaN 100 0.0
8 9 NaN 83 0.0
9 10 NaN 78 1.0
10 11 X 68 NaN
11 12 NaN 53 1.0
12 13 NaN 83 1.0
13 14 Y 68 NaN
14 15 NaN 94 0.0
15 16 NaN 50 1.0
16 17 NaN 71 1.0
17 18 NaN 71 0.0
18 19 NaN 52 0.0
19 20 NaN 67 1.0
20 21 NaN 82 0.0
21 22 X 76 NaN
22 23 NaN 66 0.0
23 24 NaN 92 1.0
我读了你的示例数据如下:
df = pd.read_fwf('input.txt', widths=[7, 6, 3], na_values=['None'])
注意na_values=['None']
,其中规定输入None(一个字符串)
读作 NaN.
这样DataFrame是:
ROWNUM A B
0 1 NaN 68
1 2 NaN 83
2 3 X 51
3 4 NaN 66
4 5 NaN 90
5 6 Y 81
6 7 NaN 81
7 8 NaN 100
8 9 NaN 83
9 10 NaN 78
10 11 X 68
11 12 NaN 53
12 13 NaN 83
13 14 Y 69
14 15 NaN 94
15 16 NaN 50
16 17 NaN 71
17 18 NaN 71
18 19 NaN 52
19 20 NaN 67
20 21 NaN 82
21 22 X 76
22 23 NaN 66
23 24 NaN 92
完成任务的代码是:
res = df.index[df.A.notnull()].to_series().rolling(4).apply(
lambda x: df.loc[x[2]:x[3], 'B'].min() > df.loc[x[0]:x[1], 'B'].min(), raw=True)\
.dropna().map(lambda x: 'YES' if x > 0 else 'NO').rename('Result')
df = df.join(res)
df.Result.fillna('', inplace=True)
如您所见,这部分是对您的代码稍作改动,但也有一些
添加。
结果是:
ROWNUM A B Result
0 1 NaN 68
1 2 NaN 83
2 3 X 51
3 4 NaN 66
4 5 NaN 90
5 6 Y 81
6 7 NaN 81
7 8 NaN 100
8 9 NaN 83
9 10 NaN 78
10 11 X 68
11 12 NaN 53
12 13 NaN 83
13 14 Y 69 YES
14 15 NaN 94
15 16 NaN 50
16 17 NaN 71
17 18 NaN 71
18 19 NaN 52
19 20 NaN 67
20 21 NaN 82
21 22 X 76 NO
22 23 NaN 66
23 24 NaN 92
我的解决方案相对于其他解决方案的优势在于:
- 内容是YES或NO,随便你,
- 对于 A 列中的非空值,此内容 仅显示 ,
"ignoring" 前 3 个,不够 "predecessors".
浏览了 64 次
0
我在包含超过 1000 行的数据框中有两列。 A 列可以取值 X、Y、None。 B 列包含从 50 到 100 的随机数。
每次在A列中出现非'None'次,就认为是第4次出现。因此,A 列中上一个非 None 事件将是 occurrence3,之前的事件将是 occurrence2,之前的事件将是 occurrence1。我想找到 occurrence4 和 occurrence3 之间的 B 列的最小值,并检查它是否大于 occurrence2 和 occurrence1 之间的 B 列的最小值。结果可以作为 "YES" 或 "NO".
存储在数据框中的新列中样本输入
ROWNUM A B
1 None 68
2 None 83
3 X 51
4 None 66
5 None 90
6 Y 81
7 None 81
8 None 100
9 None 83
10 None 78
11 X 68
12 None 53
13 None 83
14 Y 68
15 None 94
16 None 50
17 None 71
18 None 71
19 None 52
20 None 67
21 None 82
22 X 76
23 None 66
24 None 92
例如,我需要找到 B 列在 ROWNUM 14 和 ROWNUM 11 之间的最小值,并检查它是否大于 B 列在 ROWNUM 6 和 ROWNUM 3 之间的最小值。接下来,我需要找到ROWNUM 22 和 ROWNUM 14 之间的最小值,并检查它是否大于 ROWNUM 11 和 ROWNNUM 6 之间的最小值,依此类推。
编辑:
在示例数据中,我们从第 14 行开始计算,因为这是我们第四次出现非 none 列 A。第 14 行和第 11 行之间的最小值为 53。第 6 行和第 3 行之间的最小值为 51。由于 53 > 51,这意味着 B 列在第 4 次和第 3 次之间的最小值大于第 2 次和第 1 次之间 B 列的最小值。因此,输出为第 14 行将是 "YES" 或 1.
接下来,在第22行,第22行和第14行之间的最小值为50。第11行和第6行之间的最小值为68。由于50 < 68,这意味着第4次出现和第3次出现之间的最小值不是大于第 2 次出现和第 1 次出现之间的最小值。因此,第 22 行的输出将为 "NO" 或 0。
我有以下代码。
import numpy as np
import pandas as pd
df = pd.DataFrame([[0, 0]]*100, columns=list('AB'), index=range(1, 101))
df.loc[[3, 6, 11, 14, 22, 26, 38, 51, 64, 69, 78, 90, 98], 'A'] = 1
df['B'] = np.random.randint(50, 100, size=len(df))
df['result'] = df.index[df['A'] != 0].to_series().rolling(4).apply(
lambda x: df.loc[x[2]:x[3], 'B'].min() > df.loc[x[0]:x[1], 'B'].min(), raw=True)
print(df)
当 A 列有输入 [0,1] 时,此代码有效。但是我需要一个代码,其中 A 列可以包含 [None, X, Y]。此外,此代码生成的输出为 [0,1]。我需要输出为 [YES, NO]。
这是我的方法:
def is_incr(x):
return x[:2].min() > x[2:].min()
# replace with s = df['A'] == 'None' if needed
s = df['A'].isna()
df['new_col'] = df.loc[s, 'B'].rolling(4).apply(is_incr)
输出:
ROWNUM A B new_col
0 1 NaN 68 NaN
1 2 NaN 83 NaN
2 3 X 51 NaN
3 4 NaN 66 NaN
4 5 NaN 90 1.0
5 6 Y 81 NaN
6 7 NaN 81 0.0
7 8 NaN 100 0.0
8 9 NaN 83 0.0
9 10 NaN 78 1.0
10 11 X 68 NaN
11 12 NaN 53 1.0
12 13 NaN 83 1.0
13 14 Y 68 NaN
14 15 NaN 94 0.0
15 16 NaN 50 1.0
16 17 NaN 71 1.0
17 18 NaN 71 0.0
18 19 NaN 52 0.0
19 20 NaN 67 1.0
20 21 NaN 82 0.0
21 22 X 76 NaN
22 23 NaN 66 0.0
23 24 NaN 92 1.0
我读了你的示例数据如下:
df = pd.read_fwf('input.txt', widths=[7, 6, 3], na_values=['None'])
注意na_values=['None']
,其中规定输入None(一个字符串)
读作 NaN.
这样DataFrame是:
ROWNUM A B
0 1 NaN 68
1 2 NaN 83
2 3 X 51
3 4 NaN 66
4 5 NaN 90
5 6 Y 81
6 7 NaN 81
7 8 NaN 100
8 9 NaN 83
9 10 NaN 78
10 11 X 68
11 12 NaN 53
12 13 NaN 83
13 14 Y 69
14 15 NaN 94
15 16 NaN 50
16 17 NaN 71
17 18 NaN 71
18 19 NaN 52
19 20 NaN 67
20 21 NaN 82
21 22 X 76
22 23 NaN 66
23 24 NaN 92
完成任务的代码是:
res = df.index[df.A.notnull()].to_series().rolling(4).apply(
lambda x: df.loc[x[2]:x[3], 'B'].min() > df.loc[x[0]:x[1], 'B'].min(), raw=True)\
.dropna().map(lambda x: 'YES' if x > 0 else 'NO').rename('Result')
df = df.join(res)
df.Result.fillna('', inplace=True)
如您所见,这部分是对您的代码稍作改动,但也有一些 添加。
结果是:
ROWNUM A B Result
0 1 NaN 68
1 2 NaN 83
2 3 X 51
3 4 NaN 66
4 5 NaN 90
5 6 Y 81
6 7 NaN 81
7 8 NaN 100
8 9 NaN 83
9 10 NaN 78
10 11 X 68
11 12 NaN 53
12 13 NaN 83
13 14 Y 69 YES
14 15 NaN 94
15 16 NaN 50
16 17 NaN 71
17 18 NaN 71
18 19 NaN 52
19 20 NaN 67
20 21 NaN 82
21 22 X 76 NO
22 23 NaN 66
23 24 NaN 92
我的解决方案相对于其他解决方案的优势在于:
- 内容是YES或NO,随便你,
- 对于 A 列中的非空值,此内容 仅显示 , "ignoring" 前 3 个,不够 "predecessors".