如何基于多个条件用前一行填充pandas数据帧列的行



免责声明:这可能是重复的,但我找不到确切的解决方案。请随时将此问题标记为重复问题,并在评论中提供重复问题的链接。

我仍在学习python数据帧操作,这可能有一个非常简单的解决方案,但我无法理解。

我有一个带有单列的python数据帧。现在,如果满足某些条件,我想将每行的值更改为前一行的值。我已经创建了一个循环解决方案来实现这一点,但我希望有一个更有效的解决方案。

创建初始数据:

import numpy as np
import pandas as pd
data = np.random.randint(5,30,size=20)
df = pd.DataFrame(data, columns=['random_numbers'])
print(df)
random_numbers
0                6
1               24
2               29
3               18
4               22
5               17
6               12
7                7
8                6
9               27
10              29
11              13
12              23
13               6
14              25
15              24
16              16
17              15
18              25
19              19

现在假设两个条件是1(值小于10和2(值大于20。在任何一种情况下,请将行值设置为前一行值。这已经在循环格式中实现如下:

for index,row in df.iterrows():
if index == 0:
continue;
if(row.random_numbers<10):
df.loc[index,'random_numbers']=df.loc[index-1,'random_numbers']
if(row.random_numbers>20):
df.loc[index,'random_numbers']=df.loc[index-1,'random_numbers']
random_numbers
0                6
1                6
2                6
3               18
4               18
5               17
6               12
7               12
8               12
9               12
10              12
11              13
12              13
13              13
14              13
15              13
16              16
17              15
18              15
19              19

请建议一种更有效的方法来实现这个逻辑,因为我正在使用大量的行。

您可以用NaN替换小于10和大于20的值,然后使用panda。DataFrame.fill((,用前一行的值填充nan。

mask = (df['random_numbers'] < 10) | (df['random_numbers'] > 20)
# Since you escape with `if index == 0:`
mask[df.index[0]] = False
df.loc[mask, 'random_numbers'] = np.nan
df['random_numbers'].ffill(inplace=True)
# Original
random_numbers
0                7
1               28
2                8
3               14
4               12
5               20
6               21
7               11
8               16
9               27
10              19
11              23
12              18
13               5
14               6
15              11
16               6
17               8
18              17
19               8
# After replaced
random_numbers
0              7.0
1              7.0
2              7.0
3             14.0
4             12.0
5             20.0
6             20.0
7             11.0
8             16.0
9             16.0
10            19.0
11            19.0
12            18.0
13            18.0
14            18.0
15            11.0
16            11.0
17            11.0
18            17.0
19            17.0

我们也可以用一种更简单的方法来实现,将.mask().ffill()一起使用,并对[1:]进行切片,如下所示:

df['random_numbers'][1:] = df['random_numbers'][1:].mask((df['random_numbers'] < 10) | (df['random_numbers'] > 20))
df['random_numbers'] = df['random_numbers'].ffill(downcast='infer')

.mask()测试条件,并在条件为true时用NaN替换(如果未提供参数other=,则默认为用NaN替换(。保留不满足条件的行的原始值。

注意,通过在对.ffill()的调用中提供downcast='infer',结果数字被保持为integer,而不是意外地将转换为float类型。

我们在第一行使用[1:]来确保行0上的数据在没有转换的情况下不受影响。

# Original data:  (reusing your sample data)
random_numbers
0                6
1               24
2               29
3               18
4               22
5               17
6               12
7                7
8                6
9               27
10              29
11              13
12              23
13               6
14              25
15              24
16              16
17              15
18              25
19              19

# After transposition:
random_numbers
0                6
1                6
2                6
3               18
4               18
5               17
6               12
7               12
8               12
9               12
10              12
11              13
12              13
13              13
14              13
15              13
16              16
17              15
18              15
19              19

最新更新