【问题标题】:How to populate rows of pandas dataframe column based with previous row based on a multiple conditions?如何根据多个条件使用前一行填充熊猫数据框列的行?
【发布时间】:2021-05-07 15:11:25
【问题描述】:

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

我仍在学习 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

由于我使用大量行,请建议一种更有效的方法来实现此逻辑。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以将小于 10 和大于 20 的值替换为 NaN,然后使用 pandas.DataFrame.ffill() 将 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
    

    【讨论】:

    • 不错,我建议的唯一更改是放弃 inplace=True 并使用变量赋值 see this thread
    【解决方案2】:

    我们还可以通过将.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() 测试条件并在条件为真时替换为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
    
    

    【讨论】:

      猜你喜欢
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 2019-04-28
      • 2016-12-11
      • 1970-01-01
      相关资源
      最近更新 更多