在每分钟采样的pandas时间序列数据框中查找间隙,并用新行填充这些间隙。

7

问题

我有一个包含金融数据的数据框,以1分钟间隔采样。偶尔会出现一行或两行数据缺失的情况。

  • 我正在寻找一种好的(简单高效的)方法,在数据缺失的点处将新行插入到数据框中。
  • 新行可以是空的,除了索引外,索引应该包含时间戳。

例如:

 #Example Input---------------------------------------------
                      open     high     low      close
 2019-02-07 16:01:00  124.624  124.627  124.647  124.617  
 2019-02-07 16:04:00  124.646  124.655  124.664  124.645  

 # Desired Ouput--------------------------------------------
                      open     high     low      close
 2019-02-07 16:01:00  124.624  124.627  124.647  124.617  
 2019-02-07 16:02:00  NaN      NaN      NaN      NaN
 2019-02-07 16:03:00  NaN      NaN      NaN      NaN
 2019-02-07 16:04:00  124.646  124.655  124.664  124.645 

我的当前方法基于这篇文章 - 使用pandas查找时间序列数据中的缺失分钟数据,仅说明如何标识间隙,而不是如何填充它们。
我的做法是创建一个1分钟间隔的DateTimeIndex。然后,利用此索引,我创建了一个全新的数据框,将其合并到原始数据框中,从而填补了空缺。代码如下。这似乎是一个绕弯的方式,我想知道是否有更好的方法。也许可以通过重采样数据来实现?
import pandas as pd
from datetime import datetime

# Initialise prices dataframe with missing data
prices = pd.DataFrame([[datetime(2019,2,7,16,0),  124.634,  124.624, 124.65,   124.62],[datetime(2019,2,7,16,4), 124.624,  124.627,  124.647,  124.617]])
prices.columns = ['datetime','open','high','low','close']
prices = prices.set_index('datetime')
print(prices)

# Create a new dataframe with complete set of time intervals
idx_ref = pd.DatetimeIndex(start=datetime(2019,2,7,16,0), end=datetime(2019,2,7,16,4),freq='min')
df = pd.DataFrame(index=idx_ref)

# Merge the two dataframes 
prices = pd.merge(df, prices, how='outer', left_index=True, 
right_index=True)
print(prices)
3个回答

16

使用 DataFrame.asfreq 处理 Datetimeindex

prices = prices.set_index('datetime').asfreq('1Min')
print(prices)
                        open     high      low    close
datetime                                               
2019-02-07 16:00:00  124.634  124.624  124.650  124.620
2019-02-07 16:01:00      NaN      NaN      NaN      NaN
2019-02-07 16:02:00      NaN      NaN      NaN      NaN
2019-02-07 16:03:00      NaN      NaN      NaN      NaN
2019-02-07 16:04:00  124.624  124.627  124.647  124.617

1
一个更手动的答案是:

from datetime import datetime, timedelta
from dateutil import parser

import pandas as pd



df = pd.DataFrame({
 'a': ['2021-02-07 11:00:30', '2021-02-07 11:00:31', '2021-02-07 11:00:35'],
 'b': [64.8, 64.8, 50.3]
})

max_dt = parser.parse(max(df['a']))
min_dt = parser.parse(min(df['a']))


dt_range = []
while min_dt <= max_dt:
  dt_range.append(min_dt.strftime("%Y-%m-%d %H:%M:%S"))
  min_dt += timedelta(seconds=1)


complete_df = pd.DataFrame({'a': dt_range})
final_df = complete_df.merge(df, how='left', on='a')

它将以下数据框转换为:
                     a     b
0  2021-02-07 11:00:30  64.8
1  2021-02-07 11:00:31  64.8
2  2021-02-07 11:00:35  50.3

至:

                     a     b
0  2021-02-07 11:00:30  64.8
1  2021-02-07 11:00:31  64.8
2  2021-02-07 11:00:32   NaN
3  2021-02-07 11:00:33   NaN
4  2021-02-07 11:00:34   NaN
5  2021-02-07 11:00:35  50.3

我们可以稍后填充其空值


1

@jezrael 的 建议 最初对我没有起作用,因为我的 index 类型与 DatetimeIndex 不同。执行 prices.asfreq() 会清除所有 prices 数据,尽管它用 Nan 填补了间隙:

                         open     high      low    close
datetime                                               
2019-02-07 16:00:00      NaN      NaN      NaN      NaN
2019-02-07 16:01:00      NaN      NaN      NaN      NaN
2019-02-07 16:02:00      NaN      NaN      NaN      NaN
2019-02-07 16:03:00      NaN      NaN      NaN      NaN
2019-02-07 16:04:00      NaN      NaN      NaN      NaN

为了解决这个问题,我必须像这样更改index列的类型。
prices['date'] = pd.to_datetime(prices['datetime'])
prices = prices.set_index('date')
prices.drop(['datetime'], axis=1, inplace=True)

这段代码将会把 'datetime' 列的数据类型转换为 DatetimeIndex 类型,并且把这个新列设为 index

现在我可以调用

prices = prices.asfreq('1Min')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接