【问题标题】:Add extra column as the cumulative time difference添加额外的列作为累积时间差
【发布时间】:2017-07-21 03:27:57
【问题描述】:

如何添加一个额外的列,即每门课程的时差累积值?比如初始表是:

 id_A       course     weight                ts_A       value
 id1        cotton     3.5       2017-04-27 01:35:30  150.000000
 id1        cotton     3.5       2017-04-27 01:36:00  416.666667
 id1        cotton     3.5       2017-04-27 01:36:30  700.000000
 id1        cotton     3.5       2017-04-27 01:37:00  950.000000
 id2     cotton blue   5.0       2017-04-27 02:35:30  150.000000
 id2     cotton blue   5.0       2017-04-27 02:36:00  450.000000
 id2     cotton blue   5.0       2017-04-27 02:36:30  520.666667
 id2     cotton blue   5.0       2017-04-27 02:37:00  610.000000

预期结果是:

 id_A       course     weight                ts_A       value      cum_delta_sec
 id1        cotton     3.5       2017-04-27 01:35:30  150.000000      0
 id1        cotton     3.5       2017-04-27 01:36:00  416.666667      30 
 id1        cotton     3.5       2017-04-27 01:36:30  700.000000      60
 id1        cotton     3.5       2017-04-27 01:37:00  950.000000      90
 id2     cotton blue   5.0       2017-04-27 02:35:30  150.000000      0
 id2     cotton blue   5.0       2017-04-27 02:36:00  450.000000      30
 id2     cotton blue   5.0       2017-04-27 02:36:30  520.666667      60
 id2     cotton blue   5.0       2017-04-27 02:37:00  610.000000      90

【问题讨论】:

    标签: python pandas dataframe timestamp


    【解决方案1】:

    您可以将diff 方法与cumsum 链接起来:

    # convert ts_A to datetime type
    df.ts_A = pd.to_datetime(df.ts_A)
    
    # convert ts_A to seconds, group by id and then use transform to calculate the cumulative difference
    df['cum_delta_sec'] = df.ts_A.astype(int).div(10**9).groupby(df.id_A).transform(lambda x: x.diff().fillna(0).cumsum())
    df
    

    【讨论】:

    • 为什么是 div(10**9)?
    • 因为默认日期时间类型以ns(纳秒)为单位,除以10**9转换为秒为单位。
    • 感谢您的澄清。
    【解决方案2】:

    使用groupbytransform.iloc

    df['ts_A'] = pd.to_datetime(df.ts_A)
    df['cum_delta_sec'] = (df.groupby('id_A')['ts_A']
                             .transform(lambda x: (x - x.iloc[0]).dt.total_seconds()))
    

    输出:

      id_A       course  weight                ts_A       value  cum_delta_sec
    0  id1       cotton     3.5 2017-04-27 01:35:30  150.000000              0
    1  id1       cotton     3.5 2017-04-27 01:36:00  416.666667             30
    2  id1       cotton     3.5 2017-04-27 01:36:30  700.000000             60
    3  id1       cotton     3.5 2017-04-27 01:37:00  950.000000             90
    4  id2  cotton blue     5.0 2017-04-27 02:35:30  150.000000              0
    5  id2  cotton blue     5.0 2017-04-27 02:36:00  450.000000             30
    6  id2  cotton blue     5.0 2017-04-27 02:36:30  520.666667             60
    7  id2  cotton blue     5.0 2017-04-27 02:37:00  610.000000             90
    

    在组中,从第一个值中减去当前值,并使用.dt 访问器转换为秒。

    【讨论】:

    • 有几件事可以挽救我们的生命。
    【解决方案3】:
    import csv
    import datetime as dt
    
    with open('path/to/input') as fin, open('path/to/output', 'w') as fout:
        infile = csv.DictReader(fin, delimiter='\t')
        outfile = csv.DictWriter(fout, delimiter='\t', fieldnames=infile.fieldnames + ['cum_delta_sec'])
    
        cdt = 0
        last = None
        for row in infile:
            if last is None:
                last = dt.strptime(row['ts_A'], "%Y-%m-%d %H:%M:%S")
                row['cum_delta_sec'] = 0
                outfile.writerow(row)
                continue
    
            cdt += (last - dt.strptime(row['ts_A'], "%Y-%m-%d %H:%M:%S")).total_seconds()
            row['cum_delta_sec'] = cdt
            outfile.writerow(row)
    

    【讨论】:

      猜你喜欢
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 2019-10-07
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2022-07-24
      相关资源
      最近更新 更多