在另一列的两个条目之间寻找一列的最小值

时间:2019-11-27 18:52:34

标签: python pandas dataframe rolling-computation

查看了64次

0

我在包含1000多个行的数据框中有两列。列A可以采用值X,Y,None。 B列包含50到100之间的随机数。

每当列A中出现非“无”事件时,都将其视为事件4。因此,列A中的先前非None发生将是encenation3,该事件之前的将是encen2,而该事件之前的将是ocence1。我想找到在事件4和事件3之间的B列的最小值,并检查它是否大于在事件2和事件1之间的B列的最小值。结果可以以“是”或“否”的形式存储在数据框中的新列中。

样品输入

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

例如,我需要找到ROWNUM 14和ROWNUM 11之间的B列的最小值,并检查它是否大于ROWNUM 6和ROWNUM 3之间的B列的最小值。接下来,我需要找到最小值ROWNUM 22和ROWNUM 14之间的值,并检查它是否大于ROWNUM 11和ROWNNUM 6之间的最小值,等等。

编辑:

在样本数据中,我们从第14行开始计算,因为那是第A列第四个不出现的地方。第14行和第11行之间的最小值是53。在第6行和第11行之间的最小值3是51。因为53> 51,,这意味着在事件4和事件3之间的B列的最小值大于在事件2和事件1之间的B列的最小值。因此,第14行的输出为“是或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]。

2 个答案:

答案 0 :(得分:1)

这是我的方法:

server {
        listen 90;
        listen [::]:90;
        access_log /var/log/nginx/reverse-access.log;
        error_log /var/log/nginx/reverse-error.log;
        location / {
                proxy_pass http://localhost:6543;
           }
}

输出:

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)

答案 1 :(得分:1)

我读取您的示例数据如下:

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 列中的非空值显示, “忽略”前三个,没有足够的“前辈”。