3

我每十分钟就有一个盘中价格文件。[0:41] 一天。每个日期重复 42 次。下面的多索引应始终将重复的日期“折叠”为一个。

  • 有 62,035 行 x 3 列:[date, time, price].

  • 我想编写一个函数来获取十分钟价格的差异,将差异限制在每个唯一日期。

换句话说,09:30 是每天的第一次,16:20 是最后一次:我不能重叠从 16:20 到 09:30 的价格天数之间的差异。对于数据框中的每个唯一日期,差异应从 09:40 - 09:30 开始,并以 16:20 - 16:10 结束。

这是我的尝试。任何建议将不胜感激。

def diffSeries(rounded,data):

'''This function accepts a column called rounded from 'data'
 The 2nd input 'data' is a dataframe 
'''

df=rounded.shift(1)
idf=data.set_index(['date', 'time'])  
data['diff']=['000']

  for i in range(0,length(rounded)):

    for day in idf.index.levels[0]:


      for time in idf.index.levels[1]:

        if idf.index.levels[1]!=1620:

          data['diff']=rounded[i]-df[i]

        else:
          day+=1
          time+=2

data[['date','time','price','II','diff']].to_csv('final.csv')

return data['diff']

然后我打电话:

data=read_csv('file.csv')

rounded=roundSeries(data['price'],5) 

diffSeries(rounded,data)

在回溯中 - 我得到一个Assertion Error.

4

2 回答 2

1

您可以使用 groupby 然后应用来实现您想要的:

diffs = data.groupby(lambda idx: idx[0]).apply(lambda row: row - row.shift(1))

举一个完整的例子,假设您为 11 月 14 日到 11 月 16 日创建了一个测试数据集:

import pandas as pd
from numpy.random import randn
from datetime import time

# Create date range with 10 minute intervals, and filter out irrelevant times
times = pd.bdate_range(start=pd.datetime(2012,11,14,0,0,0),end=pd.datetime(2012,11,17,0,0,0), freq='10T')
filtered_times = [x for x in times if x.time() >= time(9,30) and x.time() <= time(16,20)]
prices = randn(len(filtered_times))

# Create MultiIndex and data frame matching the format of your CSV
arrays = [[x.date() for x in filtered_times]
         ,[x.time() for x in filtered_times]]
tuples = zip(*arrays)

m_index = pd.MultiIndex.from_tuples(tuples, names=['date', 'time'])
data = pd.DataFrame({'prices': prices}, index=m_index)

你应该得到一个像这样的 DataFrame:

                       prices
date       time              
2012-11-14 09:30:00  0.696054
           09:40:00 -1.263852
           09:50:00  0.196662
           10:00:00 -0.942375
           10:10:00  1.915207

如上所述,您可以通过按第一个索引分组然后减去每一行的前一行来获得差异:

diffs = data.groupby(lambda idx: idx[0]).apply(lambda row: row - row.shift(1))

这给了你类似的东西:

                       prices
date       time              
2012-11-14 09:30:00       NaN
           09:40:00 -1.959906
           09:50:00  1.460514
           10:00:00 -1.139036
           10:10:00  2.857582

由于您按日期分组,因此该功能不适用于 16:20 - 09:30。

您可能需要考虑使用 TimeSeries 而不是 DataFrame,因为这样可以为您提供更大的灵活性来处理此类数据。假设您已经从 CSV 文件加载了 DataFrame,您可以轻松地将其转换为 TimeSeries 并执行类似的功能来获取差异:

dt_index = pd.DatetimeIndex([datetime.combine(i[0],i[1]) for i in data.index])
# or dt_index = pd.DatetimeIndex([datetime.combine(i.date,i.time) for i in data.index]) 
# if you don't have an multi-level index on data yet
ts = pd.Series(data.prices.values, dt_index)
diffs = ts.groupby(lambda idx: idx.date()).apply(lambda row: row - row.shift(1))

但是,您现在可以访问内置的时间序列函数,例如重采样。有关 pandas 时间序列的更多信息,请参见此处

于 2012-11-17T01:52:15.397 回答
0

@MattiJohn 的构造给出了一个长度为 86,772 的过滤列表——在 2007 年 1 月 3 日-2012 年 8 月 30 日运行 42 次(10 分钟间隔)时。观察数据清洗问题。

这里来自 csv 的价格数据是长度:62,034。因此,简单地从 .csv 导入,如下所示,是有问题的:

filtered_times = [x for x in times if x.time() >= time(9,30) and x.time() <= time(16,20)]
DF=pd.read_csv('MR10min.csv')
prices = DF.price
 # I.E. rather than the generic: prices = randn(len(filtered_times))  above.

实际数据没有达到“应该”的长度这一事实意味着存在数据清理问题。通常我们没有完整的时间,因为 bdate_time 会产生(市场上的半天,等等,假期)

您的解决方案很优雅。但我不确定如何克服实际数据与先验规定数据帧之间的不匹配。

您的第二个 TimesSeries 建议似乎仍然需要构建类似于第一个的日期时间索引。例如,如果我使用以下两行来获取感兴趣的实际数据:

DF=pd.read_csv('MR10min.csv')
data=pd.DF.set_index(['date','time'])


dt_index = pd.DatetimeIndex([datetime.combine(i[0],i[1]) for i in data.index])

它将生成一个:

TypeError: combine() argument 1 must be datetime.date, not str

如何使 bdate_time 数组完全了解可用的实际数据?

感谢 (@MattiJohn) 和任何有兴趣继续讨论的人。

于 2012-12-10T23:07:33.203 回答