【问题标题】:DataFrame resample on date rangesDataFrame 在日期范围内重新采样
【发布时间】:2018-03-11 02:25:44
【问题描述】:

我有一个包含列的 DataFrame 'start_time'(日期时间)、'end_time'(日期时间)、'mode'和其他一些列。 表格不同行的范围没有重叠。

我想创建一个新的 DataFrame,它对原始 DataFrame 的每一行重新采样,如下所示: 'current_time', 'mode', 其他列

其中 'current_time' 是原始 'start_time' 和 'end_time' 在给定频率之间的重新采样,所有其他列只是原始表中值的副本。

示例: 原始数据框:

             start_time                   end_time   mode
2017-06-01 06:38:00.000 2017-06-01    06:39:00.000      x
2017-06-01 17:22:00.000 2017-06-01    17:22:30.000      y

对于给定的“10S”“频率”,我想获得以下数据帧:

           current_time     mode
2017-06-01 06:38:00.000        x
2017-06-01 06:38:10.000        x
2017-06-01 06:38:20.000        x
2017-06-01 06:38:30.000        x
2017-06-01 06:38:40.000        x
2017-06-01 06:38:50.000        x
2017-06-01 17:22:00.000        y
2017-06-01 17:22:10.000        y
2017-06-01 17:22:20.000        y

我正在寻找一种相当有效和优雅的方式来做到这一点。

非常感谢!

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    你可以使用:

    #convert columns to datetimes if necessary
    df['start_time']= pd.to_datetime(df['start_time'])
    df['end_time']= pd.to_datetime(df['end_time'])
    #subtract 10s for no last row from values from end_time column
    df['end_time']= df['end_time'] - pd.Timedelta(10, unit='s')
    

    #loop by list comprehension for list of date ranges
    #concat to one big DataFrame
    df1 = (pd.concat([pd.Series(r.Index, 
                               pd.date_range(r.start_time, r.end_time, freq='10S')) 
                               for r in df.itertuples()])
            .reset_index())
    df1.columns = ['current_time','idx']
    print (df1)
             current_time  idx
    0 2017-06-01 06:38:00    0
    1 2017-06-01 06:38:10    0
    2 2017-06-01 06:38:20    0
    3 2017-06-01 06:38:30    0
    4 2017-06-01 06:38:40    0
    5 2017-06-01 06:38:50    0
    6 2017-06-01 17:22:00    1
    7 2017-06-01 17:22:10    1
    8 2017-06-01 17:22:20    1
    

    通过 OP 的评论编辑:

    如果使用参数closed=left

    pd.date_range(r.start_time, r.end_time, freq='10S', closed='left')
    

    那么可以省略减法。


    #join all another columns by index
    df2 = df1.set_index('idx').join(df.drop(['start_time','end_time'], 1)).reset_index(drop=True)
    print (df2)
             current_time mode
    0 2017-06-01 06:38:00    x
    1 2017-06-01 06:38:10    x
    2 2017-06-01 06:38:20    x
    3 2017-06-01 06:38:30    x
    4 2017-06-01 06:38:40    x
    5 2017-06-01 06:38:50    x
    6 2017-06-01 17:22:00    y
    7 2017-06-01 17:22:10    y
    8 2017-06-01 17:22:20    y
    

    另一种解决方案:

    #create column from index for last join (index values has to be unique)
    df = df.reset_index()
    #reshape dates to datetimeindex
    df1 = (df.melt(df.columns.difference(['start_time','end_time']),
                  ['start_time', 'end_time'],
                  value_name='current_time')
            .drop('variable', 1)
            .set_index('current_time'))
    print (df1)
                         index mode
    current_time                   
    2017-06-01 06:38:00      0    x
    2017-06-01 17:22:00      1    y
    2017-06-01 06:38:50      0    x
    2017-06-01 17:22:20      1    y
    
    #group by index column and resample, NaNs are replaced by forward filling
    df2 = df1.groupby('index').resample('10S').ffill().reset_index(0, drop=True).drop('index', 1)
    print (df2)
                        mode
    current_time            
    2017-06-01 06:38:00    x
    2017-06-01 06:38:10    x
    2017-06-01 06:38:20    x
    2017-06-01 06:38:30    x
    2017-06-01 06:38:40    x
    2017-06-01 06:38:50    x
    2017-06-01 17:22:00    y
    2017-06-01 17:22:10    y
    2017-06-01 17:22:20    y
    

    【讨论】:

    • 谢谢!我使用了第一个解决方案,稍作修改:pd.date_range(r.start_time, r.end_time, freq='10S', closed='left')
    • 超级棒,改进的不错。
    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2020-10-18
    • 1970-01-01
    • 2018-05-22
    • 2013-01-31
    相关资源
    最近更新 更多