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

Python 在另一列的两个条目之间查找列的最小值,python,pandas,dataframe,rolling-computation,Python,Pandas,Dataframe,Rolling Computation,浏览64次 0 我在一个包含1000多行的数据框中有两列。列A可以取值X、Y、None。B列包含从50到100的随机数 每次a列中出现非“无”事件时,都被视为发生4。因此,A列中先前的非无事件将是发生3,在此之前的事件将是发生2,在此之前的事件将是发生1。我想找出发生率4和发生率3之间B列的最小值,并检查它是否大于发生率2和发生率1之间B列的最小值。结果可以作为“是”或“否”存储在数据框中的新列中 样本输入 ROWNUM A B 1 None 68 2 None

浏览64次

0

我在一个包含1000多行的数据框中有两列。列A可以取值X、Y、None。B列包含从50到100的随机数

每次a列中出现非“无”事件时,都被视为发生4。因此,A列中先前的非无事件将是发生3,在此之前的事件将是发生2,在此之前的事件将是发生1。我想找出发生率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行和第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行的输出将为“否”或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]。我需要输出为[是,否]。

以下是我的方法:

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

这样,数据帧是:

    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       
与其他解决方案相比,我的解决方案的优势在于:

  • 内容为是或否,如您所愿
  • 此内容仅对列中的非空值显示, “忽略”前3个,它们没有足够的“前辈”

请将样本数据包含为文本。我已将样本数据更新为文本。是否可以出现无值2和1?每次出现非无条目时,我们将其与前三次非无条目进行比较。因此,每当发生非无事件时,我们都会检查此事件(事件4)和上一次非无事件(事件3)之间的最小值是否大于事件2和事件1之间的最小值。每次出现非无条目时,我们都会将其与前三次非无事件进行比较。因此,每当发生非无事件时,我们检查此事件(事件4)和上一次非无事件(事件3)之间的最小值是否大于事件2和事件1之间的最小值。因此,我们的结果只能从第四次非无事件开始。@Kartick我错过了
部分。只需更改
s=df['A'].notna()
。因此,NaN可以帮助您使用notnull()?这很完美。非常感谢。就像另一个解决方案的作者一样,我假设None实际上意味着“没有数据”,应该使用普遍应用的约定将其放入df中。根据某些条件,我可以得到值“X”或“Y”。如果条件失败,我认为没有。因此,我想Nan应该是完美的。而不是None(字符串),将此列的内容生成为Nan(也是一个字符串,末尾大写N)。然后,即使没有na_值参数,它们也将被读取为NaN。