通过Python中的pandas将每日库存数据转换为每周库存数据

2024-04-29 21:50:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个存储每日数据的DataFrame,如下所示:

Date              Open        High         Low       Close   Volume
2010-01-04   38.660000   39.299999   38.509998   39.279999  1293400   
2010-01-05   39.389999   39.520000   39.029999   39.430000  1261400   
2010-01-06   39.549999   40.700001   39.020000   40.250000  1879800   
2010-01-07   40.090000   40.349998   39.910000   40.090000   836400   
2010-01-08   40.139999   40.310001   39.720001   40.290001   654600   
2010-01-11   40.209999   40.520000   40.040001   40.290001   963600   
2010-01-12   40.160000   40.340000   39.279999   39.980000  1012800   
2010-01-13   39.930000   40.669998   39.709999   40.560001  1773400   
2010-01-14   40.490002   40.970001   40.189999   40.520000  1240600   
2010-01-15   40.570000   40.939999   40.099998   40.450001  1244200   

我打算把它合并成每周的数据。分组后:

  1. 日期应为每周一(此时,当周一不是交易日时,应考虑节假日情况,我们应以本周的第一个交易日为日期)。
  2. 开盘应为周一(或本周第一个交易日)开盘。
  3. 收盘应为周五(或本周最后一个交易日)收盘。
  4. 高点应该是本周交易日的最高点。
  5. 低点应该是本周交易日的最低低点。
  6. 成交量应为本周所有交易日的成交量之和。

应该是这样的:

Date              Open        High         Low       Close   Volume
2010-01-04   38.660000   40.700001   38.509998   40.290001  5925600   
2010-01-11   40.209999   40.970001   39.279999   40.450001  6234600   

目前,我的代码片段如下所示,我应该使用哪个函数将基于每日的数据映射到预期的基于每周的数据?非常感谢!

import pandas_datareader.data as web

start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2016, 12, 31)
f = web.DataReader("MNST", "yahoo", start, end, session=session)
print f

Tags: 数据webclosedatetimedateopenstartlow
3条回答

不是直接的答案,但是假设列是日期(表的转置),没有缺少日期。

'''sum up daily results in df to weekly results in wdf'''
wdf = pd.DataFrame(index = df.index)
for i in range(len(df.columns)):
    if (i!=0) & (i%7==0):
        wdf['week'+str(i//7)]= df[df.columns[i-7:i]].sum(axis = 1)

您可以resample(每周)、offset(移位)和apply聚合规则,如下所示:

logic = {'Open'  : 'first',
         'High'  : 'max',
         'Low'   : 'min',
         'Close' : 'last',
         'Volume': 'sum'}

offset = pd.offsets.timedelta(days=-6)

f = pd.read_clipboard(parse_dates=['Date'], index_col=['Date'])
f.resample('W', loffset=offset).apply(logic)

得到:

                 Open       High        Low      Close   Volume
Date                                                           
2010-01-04  38.660000  40.700001  38.509998  40.290001  5925600
2010-01-11  40.209999  40.970001  39.279999  40.450001  6234600

一般来说,假设您具有指定格式的数据帧,则需要执行以下步骤:

  1. Date放入索引
  2. resample索引。

您所拥有的是将不同的函数应用于不同列的情况。See

您可以通过各种方式重新采样。例如,你可以取数值的平均值或计数等。检查pandas resample

您还可以应用自定义聚合器(检查同一链接)。 考虑到这一点,您的案例的代码片段可以给出如下:

f['Date'] = pd.to_datetime(f['Date'])
f.set_index('Date', inplace=True)
f.sort_index(inplace=True)

def take_first(array_like):
    return array_like[0]

def take_last(array_like):
    return array_like[-1]

output = f.resample('W',                                 # Weekly resample
                    how={'Open': take_first, 
                         'High': 'max',
                         'Low': 'min',
                         'Close': take_last,
                         'Volume': 'sum'}, 
                    loffset=pd.offsets.timedelta(days=-6))  # to put the labels to Monday

output = output[['Open', 'High', 'Low', 'Close', 'Volume']]

这里,W表示每周重新采样,默认范围是从周一到周日。要将标签保留为星期一,请使用loffset。 有几个预定义的日期说明符。看看pandas offsets。您甚至可以定义自定义偏移(see)。

回到重采样方法。在这里,对于OpenClose,您可以指定自定义方法来获取第一个值等,并将函数句柄传递给how参数。

这个答案是基于这样的假设:数据似乎是每天的,即每天只有一个条目。此外,不存在非工作日的数据。i、 坐着晒太阳。所以把这周的最后一个数据点作为周五的数据点是可以的。如果你愿意的话,你可以用商务周代替“W”。此外,对于更复杂的数据,您可能需要使用groupby对每周数据进行分组,然后在其中处理时间索引。

顺便说一句,解决方案的要点可以在: https://gist.github.com/prithwi/339f87bf9c3c37bb3188

相关问题 更多 >