来自范围索引的Pandas Datetime索引

时间:2019-02-21 16:21:33

标签: pandas

我有一个带有日期和价格列的交易记录:

+---------------------------+-------+
|           Date            | Price |
+---------------------------+-------+
| 2016-05-27 10:02:24+00:00 |  2.90 |
| 2016-05-27 10:02:24+00:00 | 14.90 |
| 2016-05-29 07:47:09+00:00 | 12.90 |
| 2016-05-29 11:56:32+00:00 | 16.90 |
| 2016-05-29 22:10:08+00:00 | 11.92 |
+---------------------------+-------+

因为可以从表中了解并非每天都有交易发生,在某些情况下同一天发生了几笔交易。

我的问题是:如何创建一个日期范围从最早的事务到最新的DataFrame,并添加price 0到该DataFrame缺少的日期,同时为同一天发生的事务保留多行?下表中是一个更好的示例:

+---------------------------+-------+
|           Date            | Price |
+---------------------------+-------+
| 2016-05-27 10:02:24+00:00 |  2.90 |
| 2016-05-27 10:02:24+00:00 | 14.90 |
| 2016-05-28 00:00:00+00:00 |  0.00 |
| 2016-05-29 07:47:09+00:00 | 12.90 |
| 2016-05-29 11:56:32+00:00 | 16.90 |
| 2016-05-29 22:10:08+00:00 | 11.92 |
+---------------------------+-------+ 

我试图用DateRange从最旧的到最新的创建一个系列,然后将该系列添加到DataFrame中,但是这样做会导致缺少一些值:

d2 = pd.Series(pd.date_range(min(df.Date), max(df.Date)))

df['dates'] = d2 

2 个答案:

答案 0 :(得分:2)

您可以找到缺少的日期,然后将缺少的日期串联起来

import pandas as pd

missings = [x for x in pd.date_range(df.Date.min().date(), df.Date.max().date(), freq='1D').date
            if x not in df.Date.dt.date.unique()]

df = (pd.concat([df, pd.DataFrame({'Date': pd.to_datetime(missings).tz_localize('UTC'), 'Price': 0})])
        .sort_values('Date'))

输出:

                       Date  Price
0 2016-05-27 10:02:24+00:00   2.90
1 2016-05-27 10:02:24+00:00  14.90
0 2016-05-28 00:00:00+00:00   0.00
2 2016-05-29 07:47:09+00:00  12.90
3 2016-05-29 11:56:32+00:00  16.90
4 2016-05-29 22:10:08+00:00  11.92

还可以找到带有集合的缺失日期,应该更快一些

missings = list(set(pd.date_range(df.Date.min().date(), df.Date.max().date(), freq='1D', tz='UTC').values) 
                 - set(df.Date.dt.normalize().values))

答案 1 :(得分:0)

您可以创建一个最大/最小值daterange,外部合并和fillna为0的系列:

df.Date = pd.to_datetime(df.Date)
rng = pd.date_range(start=df.Date.min(), end=df.Date.max(), freq='D')
df = df.set_index('Date')
pd.merge(df, pd.Series(index=rng, name='rng'), how='outer', left_index=True, right_index=True).drop('rng', 1).fillna(0)

输出:

    Price
2016-05-27 10:02:24     2.900
2016-05-27 10:02:24     14.900
2016-05-28 10:02:24     0.000
2016-05-29 07:47:09     12.900
2016-05-29 10:02:24     0.000
2016-05-29 11:56:32     16.900
2016-05-29 22:10:08     11.920

请注意,为方便起见,我忽略了UTC偏移量,我认为它不会影响我的解决方案。另外请注意,插补日的时间将与最短日期相同。