【问题标题】:How can i do calculations on subsets , Panda's way, without looping如何在不循环的情况下以 Panda 的方式对子集进行计算
【发布时间】:2014-12-16 18:20:35
【问题描述】:

我有这样的日子:

eventday_idxs
2005-01-07 00:00:00
2005-01-31 00:00:00
2005-02-15 00:00:00
2005-04-18 00:00:00
2005-05-11 00:00:00
2005-08-12 00:00:00
2005-08-15 00:00:00
2005-09-06 00:00:00
2005-09-19 00:00:00
2005-10-12 00:00:00
2005-10-13 00:00:00
2005-10-20 00:00:00
2006-01-10 00:00:00
2006-01-30 00:00:00
2006-02-10 00:00:00
2006-03-29 00:00:00

我想在 AAPL 股票数据集上像这样计算 From : To 范围。
因为我是 Pandas 的初学者,所以我使用循环并这样做。

aap1_10_years = pd.io.data.get_data_yahoo('AAPL', 
                                 start=datetime.datetime(2004, 12, 10), 
                                 end=datetime.datetime(2014, 12, 10))
one_day = timedelta(days=1)
for i,ind in enumerate(eventday_idxs):
    try:
        do_calculations(aapl_10_years[ ind: eventday_idxs[i+1] - one_day ]['High'])
    except IndexError:
        do_calculations(aapl_10_years[ ind:]['High'] )

如何在没有这样的循环的情况下应用do_calcuations?因为这样的循环在 panda 中是不鼓励的,因为速度很慢,对吧?

【问题讨论】:

    标签: python function loops pandas functional-programming


    【解决方案1】:

    事件之间的时间跨度不规则:

    In [141]: eventday_idxs.diff().head()
    Out[141]: 
    0       NaT
    1   24 days
    2   15 days
    3   62 days
    4   23 days
    Name: 0, dtype: timedelta64[ns]
    

    所以我们不能使用 rolling_apply 来表达计算。然而,如果我们可以 为aap1_10_years 中的每一行分配一个“事件编号”,然后我们可以 groupby 这些事件编号并将do_calculations 应用于每个组。

    如果我们定义:

    # mark each event day with a 1
    aap1_10_years.loc[eventday_idxs, 'event'] = 1
    # use cumsum to assign an event number to each event range
    aap1_10_years['event'] = aap1_10_years['event'].fillna(0).cumsum()
    

    那么对于这些​​行,aap1_10_years['event'] 等于 1:

    In [144]: aap1_10_years.loc[aap1_10_years['event'] == 1, ['Close', 'event']]
    Out[144]: 
                Close  event
    Date                    
    2005-01-07  69.25      1
    2005-01-10  68.96      1
    2005-01-11  64.56      1
    2005-01-12  65.46      1
    2005-01-13  69.80      1
    2005-01-14  70.20      1
    2005-01-18  70.65      1
    2005-01-19  69.88      1
    2005-01-20  70.46      1
    2005-01-21  70.49      1
    2005-01-24  70.76      1
    2005-01-25  72.05      1
    2005-01-26  72.25      1
    2005-01-27  72.64      1
    2005-01-28  73.98      1
    

    因此,事件编号 1 已分配给所有日期之间的行 2005-01-07 和 2005-01-28。同样,其他每个事件范围都被分配了一个唯一的事件编号。


    import datetime as DT
    import pandas as pd
    import pandas.io.data as pdata
    eventday_idxs = pd.to_datetime(pd.read_table('data', header=None)[0])
    aap1_10_years = pdata.get_data_yahoo(
        'AAPL', 
        start=DT.datetime(2004, 12, 10), 
        end=DT.datetime(2014, 12, 10))
    
    # mark each event day with a 1
    aap1_10_years.loc[eventday_idxs, 'event'] = 1
    # use cumsum to assign an event number to each event range
    aap1_10_years['event'] = aap1_10_years['event'].fillna(0).cumsum()
    
    mask = aap1_10_years['event'] > 0
    aap1_10_years.loc[mask].groupby(['event'])['High'].apply(do_calculations)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-07
      • 2019-12-26
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 1970-01-01
      • 2015-04-23
      • 1970-01-01
      相关资源
      最近更新 更多