熊猫将值与上一行进行比较,并更改分组数据框中其余行的值

时间:2019-12-16 10:25:28

标签: python pandas dataframe

我有一个机器数据框。数据框按序列号分组,并按日期排序。每组序列号(机器)中每一列的值都在增加。数据框看起来像这样

数据框:

    serial_number   eng_hr  lifts   tons   km           date_created
6173    A1          31      50      700    10           2014-10-22
6152    A1          32      55      800    20           2015-09-10
6159    A1          33      60      900    30           2015-09-23
7070    A2          20      30      150    500          2014-04-23
7016    A2          25      40      160    600          2014-08-28
7055    A2          30      50      170    700          2014-10-28
7011    A2          35      60      180    800          2014-11-13
2189    A3          10      20      10     100          2015-03-12
2239    A3          20      30      20     200          2015-03-12
2225    A3          30      40      30     300          2015-03-23

但是,在某些情况下,当前行值与下一行的差小于0,如下表中的X + 1 = 1573行和X = 1541行所示(发生在升降机中) ,吨和公里)。该表是按日期排序的计算机的详细信息。由df[df['serial_number']=='A5'][['serial_number','eng_hr','lifts','tons','km','date_created']]导致:

      serial_number eng_hr      lifts   tons    km          date_created

1573    A5          10          50      200     20          2017-02-23
1541    A5          20          60      300     25          2017-03-17
1574    A5          30          20      100     5           2017-06-14
1553    A5          40          30      200     10          2017-08-16
1552    A5          50          40      300     15          2017-08-28
1554    A5          60          50      400     20          2017-09-22
1556    A5          70          60      500     30          2017-10-09
1550    A5          80          70      600     40          2018-12-03
1564    A5          90          80      700     50          2019-04-18

在这种情况下,我需要将当前行(行号1541)的值添加到这些特定属性中数据帧的所有下一行。因此,上一张表格应如下所示(从编号1574的行数,升程,音调和公里数开始发生变化):

      serial_number eng_hr      lifts   tons    km          date_created

1573    A5          10          50      200     20          2017-02-23
1541    A5          20          60      300     25          2017-03-17
1574    A5          30          80      400     30          2017-06-14
1553    A5          40          90      500     35          2017-08-16
1552    A5          50          100     600     40          2017-08-28
1554    A5          60          110     700     45          2017-09-22
1556    A5          70          120     800     55          2017-10-09
1550    A5          80          130     900     65          2018-12-03
1564    A5          90          140     1000    75          2019-04-18

我怎么用熊猫呢?

1 个答案:

答案 0 :(得分:0)

根据您的描述,我有一个解决方案,具体取决于您的描述(即,如果对于给定的序列号,需要进行一次调整,并且按照您的描述进行了调整,则应该可能无法推广,或者是最有效的解决方案,但是应该可以。

我首先定义一个以数据框和列列表为参数的函数。一行一行地操作如下:

  1. 重置索引,将“计算机”作为列移入数据框
  2. 如果由col标识的所有列(在您的示例['lifts','tons','km']中都发生了负变化,则创建一个等于1的虚拟变量“标志”
  3. 使用“标志”将上一行标识为“修复”(即将添加到其他行中的行)
  4. 标记数据框中需要调整的部分
  5. 将“修复”中的相关列信息添加到数据框的标记部分
  6. 将数据框重新组合在一起,将“机器”恢复为索引,然后返回数据框

代码:

def fixer(x,col):

    x = x.reset_index()
    x['flag'] = 1*((x[col] - x[col].shift())<0).all(axis='columns')
    fix = x[x['flag'].shift(-1) ==1][col]

    flagged = x['flag'].cumsum()>0
    fixed = x[flagged]
    fixed[col] = x[flagged][col].add(fix.values.tolist()[0],axis='columns')

    x = x[~flagged].append(fixed)
    x = x.drop(columns =['flag']).set_index('machine')

    return x

声明后,您可以按以下方式将其应用于每个序列号组:

df = df.groupby('serial_number').apply(fixer,['lifts','tons','km']).droplevel('serial_number')

我希望这会有所帮助。如果您遇到问题,请告诉我。