【问题标题】:Select CONSECUTIVE rows from a DataFrame based on values in a column in Pandas with Groupby使用 Groupby 根据 Pandas 中的列中的值从 DataFrame 中选择 CONSECUTIVE 行
【发布时间】:2016-06-19 14:59:42
【问题描述】:

我有 5 年的标准普尔 500 指数数据,我正试图将这些数据分组到特定的时间块中以进行一些分析。我的数据以 5 分钟为增量。在将它读入一个名为 dated 的 DataFrame 后,我想我可以按每个交易日 Globex 开盘和收盘之间的时间增量将其分组为包含连续行的块。 Globex 开盘时间为太平洋标准时间下午 3:00 (15:00),收盘时间为太平洋标准时间下午 1:15 (13:15),即 22.25 小时后。所以我想把从下午 3:00 打开到下午 1:15 的数据分块——每个块大约有 275 行。

困难在于“交易日”跨越 2 个不同的日期,例如,一个交易日在 2016 年 3 月 6 日星期日 15:00 开始,并在 3 日星期一结束-7-2016 在 13:15。我无法按“日期”列进行分组,因为当我需要数据块跨越两个日期时,所有 3-6 都将在一个块中,3-7 在另一个块中,为了将整个 Globex 日分成一大块。

对于 Pandas 和 Python 来说,我都比较陌生,我不知道使用什么方法将数据分组到我想要的块中。数据分离后,我想将每个时段/块的最高价和最低价提取到单独的列中,另外还有一列仅代表 15:05 的开盘价。

这是我的数据的示例:

    Date    Time    Open    High    Low Close   Up  Down
0   2015-08-03  15:05   2073.50 2074.00 2073.25 2073.25 210 563
1   2015-08-03  15:10   2073.25 2073.25 2072.25 2072.75 118 632
2   2015-08-03  15:15   2072.75 2072.75 2072.25 2072.50 132 85
3   2015-08-03  15:20   2072.50 2072.75 2072.25 2072.50 95  312
4   2015-08-03  15:25   2072.50 2074.00 2072.50 2073.50 372 264

最初,“日期”列值如下所示:2015 年 8 月 3 日。我认为它可能不会被读取为实际的日期对象,因此我使用 to_datetime() 更改了值,以使“日期”列值读取为像上面的示例 DataFrame 中看到的实际日期对象一样。

dated['Date'] =pd.to_datetime(dated['Date'])

当我尝试使用 to_datetime() 更改“时间”列中的值时,它成功地将时间从 15:05 更改为 15:05:00,但它也添加了日期,所以它看起来像这样: '2016-03-05 15:05:00',问题在于它使用今天的日期作为日期。这显然对我不起作用,因为我的数据是历史数据,并且日期和时间是对历史价格的参考。
我试图将“时间”列更改为日期时间对象的原因是我认为我可以在 groupby 操作期间将其切成我需要的块:

dated = dated['Date'].groupby(dated['15:05' : '13:20'])  

这产生了错误:

IndexError: invalid slice

因此,如果能帮助我解决这个问题,我将不胜感激 - 为我指明正确的研究领域。我基本上一直在逐篇阅读 pandas 文档,尝试不同的方法,但由于我不确定从什么步骤开始,所以我一直在随机选择要阅读的主题,但没有找到答案。

谢谢, 安娜

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这其实很复杂。

    首先,您可以按如下方式转换您的时间:

    df['Datetime'] = pd.to_datetime(df.Date + ' ' + df.Time)
    

    在这里,我将创建一个更大的示例数据框:

    np.random.seed(0)
    idx = pd.date_range('2015-1-1', '2016-1-1', freq='5min')
    df = pd.DataFrame(np.random.randn(len(idx), 6),    
                      columns=['Open', 'High', 'Low', 'Close', 'Up', 'Down'])
    df['Datetime'] = idx
    

    让我们添加一个布尔标志来指示市场何时开放。

    # Create a market open flag.
    df['market_open'] = False
    mask = (df.Datetime.dt.time > dt.time(15)) | (df.Datetime.dt.time < dt.time(13, 15))
    df.loc[mask, 'market_open'] = True
    

    这里我们创建一个函数,返回分组柱的开盘价、最高价、最低价、收盘价等:

    def ohlc(df):
        return (
            df.Datetime.iat[-1], # last timestamp in group.
            df.Open.iat[0], # First Open.
            df.High.max(), 
            df.Low.min(), 
            df.Close.iat[-1], # Last Close.
            df.Up.sum(), 
            df.Down.sum(),
            df.Close.count(), # Count number of closing bars.
            df.market_open.iat[0])   # Take first True/False indicator.
    

    现在我们根据market_open 中的更改(即根据真/假标志的更改)进行分组,然后将我们的函数应用于这些分组结果。

    bars = pd.DataFrame(
        zip(*df.groupby(
                (df.market_open != df.market_open.shift())
                .cumsum()
                 ).apply(ohlc))).T
    
    bars.columns = ['bar_close_time', 'Open', 'High', 'Low', 'Close', 'Up', 'Down', 'bar_count', 'market_open']
    

    我们有开放式和封闭式的酒吧。我们可以在市场关闭时删除那些。

    # Remove bars when market is closed
    bars = bars[bars.market_open].iloc[:, :-1]
    
    >>> bars.tail()
              bar_close_time      Open     High      Low      Close        Up     Down bar_count
    722  2015-12-28 13:10:00   1.23175  2.88569  -2.7143  -0.785648  -13.3166  14.6094       266
    724  2015-12-29 13:10:00 -0.900675   2.6483 -2.61698    -0.8265  0.825872  4.98565       266
    726  2015-12-30 13:10:00   1.65299  2.57881 -2.85199  -0.376141  -4.32867  3.62123       266
    728  2015-12-31 13:10:00  0.435619  2.93638 -2.74758  -0.461525  -20.0928 -15.8205       266
    730  2016-01-01 00:00:00  0.293165  2.39097  -2.1234  0.0684124  -7.83721  1.69182       108
    

    【讨论】:

    • 谢谢 Alexander,当我得到这部分代码时:dated['markt_open'] =False mask = (dated.Datetime.dt.time &gt; dt.time(15)) | (dated.Datetime.dt.time &lt; dt.time(13, 15)) dated.loc[mask, 'markt_open'] = True 我收到此错误:AttributeError: 'DataFrame' object has no attribute 'datetime' 顺便说一句,我正在使用带有 Python 2.7 的 Jupyter 笔记本 import pandas as pd import numpy as np from datetime import datetime 谷歌搜索解决方案,但我被引导到与 Series 构造函数相关的时间序列内容,而不是 DataFrame 构造函数......帮助?
    • 导入日期时间为 dt
    • 嗨亚历山大,非常感谢您的帮助,仍然是同样的错误:AttributeError: 'DataFrame' object has no attribute 'datetime' 进口调整:import pandas as pd--import numpy as np--import datetime as dt。我还修正了我的错别字。我在这里寻找 Datetime 属性:link 但没有找到 Doc。我不确定我错过了什么。
    • 您注意到我在上面的日期时间中使用了大写的D,对吧? df['Datetime'] = pd.to_datetime(df.Date + ' ' + df.Time)
    • 发现错误。我没有像你那样创建一个大的 samp/DF,而是使用我的 ES 数据文件并从 dated[‘Date Time’] 而不是 dated['Datetime'] 开始,并且没有在代码中进一步意识到它。它工作得很好——现在我只需要弄清楚它是如何工作的。我了解所有 zip()。所以我会把它分开。正如你所看到的,我边走边学。再次感谢你的帮助!!除了 McKinney 的“用于数据分析的 Python”之外,您能否推荐一些其他书籍(有这本),这些书籍教授如何创建与我正在研究的程序类似的程序?
    【解决方案2】:

    您可以考虑一个辅助日期时间列,它等于原始的减去 14 小时。那么每个交易时段将在一天之内。

    这与考虑日期时间的另一个时区相同,其中交易时段不跨越两天。

    【讨论】:

      猜你喜欢
      • 2017-01-14
      • 2018-09-04
      • 1970-01-01
      • 2017-09-23
      • 2022-11-25
      • 1970-01-01
      • 2013-06-08
      相关资源
      最近更新 更多