以 5 分钟为间隔对 DataFrame 进行分组

Posted

技术标签:

【中文标题】以 5 分钟为间隔对 DataFrame 进行分组【英文标题】:Group DataFrame in 5-minute intervals 【发布时间】:2016-08-09 11:32:07 【问题描述】:

如何使用 Python/pandas 从这个 csv 中获取 5 分钟的数据? 对于每 5 分钟的间隔,我尝试获取该 5 分钟间隔的 DATE、TIME、OPEN、HIGH、LOW、CLOSE、VOLUME。

DATE       TIME     OPEN    HIGH    LOW     CLOSE   VOLUME
02/03/1997 09:04:00 3046.00 3048.50 3046.00 3047.50 505          
02/03/1997 09:05:00 3047.00 3048.00 3046.00 3047.00 162          
02/03/1997 09:06:00 3047.50 3048.00 3047.00 3047.50 98           
02/03/1997 09:07:00 3047.50 3047.50 3047.00 3047.50 228          
02/03/1997 09:08:00 3048.00 3048.00 3047.50 3048.00 136          
02/03/1997 09:09:00 3048.00 3048.00 3046.50 3046.50 174          
02/03/1997 09:10:00 3046.50 3046.50 3045.00 3045.00 134          
02/03/1997 09:11:00 3045.50 3046.00 3044.00 3045.00 43           
02/03/1997 09:12:00 3045.00 3045.50 3045.00 3045.00 214          
02/03/1997 09:13:00 3045.50 3045.50 3045.50 3045.50 8            
02/03/1997 09:14:00 3045.50 3046.00 3044.50 3044.50 152

【问题讨论】:

问题必须显示最少的研究工作。你试过什么? 粘贴链接并不能告诉我你已经尝试过了。这并不是您在此处询问之前努力解决此问题的证明。您可以发布一些您尝试过的代码吗?如果你还没有任何代码,你可能不想在这里问,直到你这样做。 我扔了这个并尝试了很多不同的东西。 [link(pandas.pydata.org/pandas-docs/version/0.17.1/generated/…) 我尝试了 asfreq 和 clip 以及其他一些东西。我考虑了每个间隔的 .at_time 并以某种方式将它们加在一起。但我认为有更好的方法。但我会继续努力。 听起来你已经做出了相当不错的努力。如果您编辑您的问题以包含您用来尝试这些事情的代码,这将使您的问题更有帮助。描述每个代码 sn-p 以及它如何没有按您的预期工作。最好只是表明您尝试了一些事情。 我不小心发布了链接。我尝试了一些不同的东西,但我通常会在尝试后删除它们。 【参考方案1】:

您可以使用df.resample 根据日期/时间变量进行聚合。您需要一个日期时间索引,并且可以在读取 csv 文件时指定:

df = pd.read_csv("filename.csv", parse_dates = [["DATE", "TIME"]], index_col=0)

这将产生一个包含日期和时间组合索引的数据框 (source):

df.head()
Out[7]: 
                       OPEN    HIGH     LOW   CLOSE  VOLUME 
DATE_TIME                                                   
1997-02-03 09:04:00  3046.0  3048.5  3046.0  3047.5      505
1997-02-03 09:05:00  3047.0  3048.0  3046.0  3047.0      162
1997-02-03 09:06:00  3047.5  3048.0  3047.0  3047.5       98
1997-02-03 09:07:00  3047.5  3047.5  3047.0  3047.5      228
1997-02-03 09:08:00  3048.0  3048.0  3047.5  3048.0      136

之后,您可以使用 resample 来获取这五分钟间隔的总和、平均值等。

df.resample("5T").mean()
Out[8]: 
                       OPEN    HIGH     LOW   CLOSE  VOLUME 
DATE_TIME                                                   
1997-02-03 09:00:00  3046.0  3048.5  3046.0  3047.5    505.0
1997-02-03 09:05:00  3047.6  3047.9  3046.8  3047.3    159.6
1997-02-03 09:10:00  3045.6  3045.9  3044.8  3045.0    110.2
1997-02-03 09:15:00  3043.6  3044.0  3042.8  3043.2     69.2
1997-02-03 09:20:00  3044.7  3045.2  3044.5  3045.0     65.8
1997-02-03 09:25:00  3043.8  3044.0  3043.5  3043.7     59.0
1997-02-03 09:30:00  3044.6  3045.0  3044.3  3044.6     56.0
1997-02-03 09:35:00  3044.5  3044.5  3043.5  3044.5     44.0

T 用于分钟频率。Here 是其他单位的列表。)

【讨论】:

当我尝试 ("5T") 甚至 ("H") 时,我无法让它工作,我得到这个 DatetimeIndexResampler [freq=, axis=0, closed =left,label=left,convention=start,base=0]。但是当我只运行 df.resample 时,它​​可以在没有间隔调整的情况下正常工作。 您能解释一下您要进行哪种类型的调整吗? DatetimeIndexResampler [freq=<5 * Minutes>, axis=0, closed=left, label=left, convention=start, base=0] 是调用 resample 后的对象。您可以在该对象上应用方法(例如取平均值、标准偏差等)。如果您不调用任何方法,它只会返回分组。您可以将您期望的示例输出添加到问题中吗? 我只是想获得 5 分钟的间隔,而不需要任何类型的应用方法,如均值、标准差。几乎与您所做的完全一样,而不仅仅是 5 分钟的间隔 可能得到我正在寻找的答案是(最高的最高价)和(最低价的最低价)和(第一个区间为开盘)和(最后一个区间为收盘)和(总和)5分钟间隔内的所有内容。我现在正在查找它是否可能。【参考方案2】:

使用pandas 的另一种方法是使用它的TimeGrouper 函数。 它的目的仅适用于像您这样的用例。

import pandas as pd

df = pd.DataFrame("Your data provided above")
df["DATE"] = pd.to_datetime(df["DATE"])
df.set_index("DATE", inplace=True)

df = df.groupby(pd.TimeGrouper('5Min')).agg(
                                        "OPEN":  "first",
                                        "HIGH":  "max",
                                        "LOW":   "min",
                                        "CLOSE": "last",
                                        "VOLUME": "sum"
                                    )

提供的脚本使用了您在处理股票数据时可能想到的聚合。它以某种方式聚合,您最终会得到由 1 分钟蜡烛产生的 5 分钟蜡烛。

【讨论】:

很好的解决方案。但它将 5 分钟数据分组并添加到时间框架的开头。例如:将 9:00,9:01,9:022,9:03,9:04 分组,并将时间值分配为 9:00 。但预计将 9:01,9:022,9:03 分组,9:04,9:05 并将其设置为 9:05 @defender:你描述它的行为是正确的 :) 然而,对于金融数据,这是一个经常使用的聚合并且通常非常常见(这也是 pandas-devs 像这样实现它的原因),所以我不会将其描述为意外或不希望的结果。但当然重要的是指出它的工作方式,以便任何人都知道他/她从中得到了什么——谢谢! :) 在最新版本的 pandas 中,使用pd.Grouper @AbhilashAwasthi:不完全正确,看后卫和我的讨论;结果各不相同。 @Markus 我只是指pd.TimeGrouper 在新版本的熊猫中已被弃用,应该使用pd.Grouper。看到这个-***.com/questions/45156289/…。我没有评论结果变化。【参考方案3】:

对 Markus 的回答稍作修改。它分组并将其分配给最后一个索引

df_close_left = data_set.groupby(pd.Grouper(freq='5Min',closed='right',label='right')).agg(
                                        "open":  "first",
                                        "high":  "max",
                                        "low":   "min",
                                        "close": "last",
                                        "volume": "sum"

                                    )

【讨论】:

以上是关于以 5 分钟为间隔对 DataFrame 进行分组的主要内容,如果未能解决你的问题,请参考以下文章

按 15 分钟间隔对 mysql 查询进行分组

在一个时间范围内分组为 5 分钟的间隔

按 1 分钟间隔分组操作链 sql BigQuery

将 DateTime 分组为 5、15、30 和 60 分钟间隔

有没有办法在 DuckDB 中按 15 分钟的间隔进行分组?

在 MongoDb 中按 15 分钟的时间间隔对结果进行分组