使用 datetime.time 类型重采样熊猫索引

时间:2021-07-17 08:16:25

标签: python pandas dataframe datetime

我有一个数据集,它有一个与日期无关的 datetime.time (hour:minute) 索引,如下所示:

<头>
时间 11/22/16 11/23/16 11/24/16
00:00 50.9 51.3 49
00:01 50.8 51.8 49.9
00:02 51.4 52.6 48.3

我正在尝试对日期不可知的时间段进行各种统计,例如(avg、stddev 等) 时间为 00:01,因此让它们像这样对齐有助于解决这个问题,但似乎与日期无关的索引使得与 Pandas 的其他部分一起工作变得更加困难。如果我只是重新组织数据集以便三个日期列是一个连续列并且索引是一个真正的日期时间时间戳,是否有人有关于如何处理这样的日期不可知索引或如何进行日期不可知统计的建议?

我现在面临的特殊问题是我想使用 forward fill 对数据集进行上采样,使其每分钟有 60 个样本(秒精度)。

因此生成的 df 将类似于:

<头>
时间 11/22/16 11/23/16 11/24/16
00:00:00 50.9 51.3 49
00:00:01 50.9 51.3 49
00:00:02 50.9 51.3 49
00:00:03 50.9 51.3 49
00:01:00 50.8 51.8 49.9
00:02:00 51.4 52.6 48.3

我遇到的问题是 resample 不接受 datetime.time 作为`DateTime-like index'。我可以向初始数据集添加一个人工日期,例如:

<头>
时间 11/22/16 11/23/16 11/24/16
1899-12-30 00:00:00 50.9 51.3 49
1899-12-30 00:01:00 50.8 51.8 49.9
1899-12-30 00:02:00 51.4 52.6 48.3

但这似乎有点荒谬。我还想出了一种使用 explode 来做到这一点的方法:

df['ListOfTimes'] = pd.Series(
        [np.full((1, 60), df['Time'][x]).tolist()[0] for x in range((len(df.index)))])
    df = df.explode('ListOfTimes')

但是做这样的事情比创建和调试要痛苦得多,而不仅仅是df.resample('60S').ffill()。寻找最以熊猫为中心的方式来处理与日期无关的时间索引。

2 个答案:

答案 0 :(得分:1)

一种方法是创建一个生成器,使用 f-string 生成时间间隔,然后使用 reindex

s = (f"{i}:{n:02}" for i in df["Time"] for n in range(0, 60))

print (df.assign(Time=df["Time"]+":00").set_index("Time").reindex(s).ffill())

          11/22/16  11/23/16  11/24/16
Time                                  
00:00:00      50.9      51.3      49.0
00:00:01      50.9      51.3      49.0
00:00:02      50.9      51.3      49.0
00:00:03      50.9      51.3      49.0
00:00:04      50.9      51.3      49.0
...            ...       ...       ...
00:02:55      51.4      52.6      48.3
00:02:56      51.4      52.6      48.3
00:02:57      51.4      52.6      48.3
00:02:58      51.4      52.6      48.3
00:02:59      51.4      52.6      48.3

[180 rows x 3 columns]

答案 1 :(得分:0)

您可以将 DataFrame 重新排列为时间序列、重新采样,然后回到您的每列一天的格式,如下所示:

import pandas as pd

# One day per column.  We will upsample from four to two hours.
df = pd.DataFrame({'2020-01-01': [1,2,3,4,5,6], '2020-01-02': [7,8,9,10,11,12]}, 
                  index=['0:00', '4:00', '8:00', '12:00', '16:00', '20:00'])

# One-liner
df.stack() \
  .reset_index() \
  .apply(lambda x: (pd.Timestamp(x['level_1']+'T'+x['level_0']), x[0]), 
         axis='columns', result_type='expand') \
  .set_index(0) \
  .resample('2H').ffill() \
  .reset_index() \
  .apply(lambda x: (str(x[0].date()), str(x[0].time()), x[1]), 
         axis='columns', result_type='expand') \
  .set_index([1,0]) \
  .unstack() \
  .ffill()

结果是:

                  2           
0        2020-01-01 2020-01-02
1                             
00:00:00        1.0        7.0
02:00:00        1.0        7.0
04:00:00        2.0        8.0
06:00:00        2.0        8.0
08:00:00        3.0        9.0
10:00:00        3.0        9.0
12:00:00        4.0       10.0
14:00:00        4.0       10.0
16:00:00        5.0       11.0
18:00:00        5.0       11.0
20:00:00        6.0       12.0
22:00:00        6.0       12.0