熊猫:通过对重采样窗口中数据的前n个百分位数进行加权平均来对数据进行重采样

时间:2019-08-21 23:43:43

标签: pandas aggregate pandas-groupby resampling

我有以下数据

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

date_today = pd.Timestamp(1513393355.5, unit='s')
days = pd.date_range(date_today, date_today + timedelta(1), freq='s')

np.random.seed(seed=1111)
data_price = np.random.randint(2, high=10, size=len(days))
data_quantity = np.random.randint(2, high=100, size=len(days))

df = pd.DataFrame({'ts': days, 'price': data_price, 'quantity': data_quantity})
df = df.set_index('ts')
print(df.head())

                         price  quantity
ts                                      
2017-12-16 03:02:35.500      6        30
2017-12-16 03:02:36.500      9        18
2017-12-16 03:02:37.500      7        85
2017-12-16 03:02:38.500      3        51
2017-12-16 03:02:39.500      6        19

我想以10分钟为间隔对数据进行重新采样,按照价格的升序对每个10分钟窗口内的观察结果进行排名,对排名后的数据进行前20%的排序,然后计算加权平均价格(即价格加权后的价格)按数量),以及数据的前20%的数量之和。

有一个解决方案https://stackoverflow.com/a/29820981/220986,该解决方案使用groupby函数来计算加权平均价格。但是我想将加权平均值应用于总和的前20%。

我想在静态基础上(即应用熊猫重采样功能),并每隔1分钟滚动一次,回溯期为10分钟。

我如何用熊猫优雅地做到这一点?我对如何在重采样窗口中进行排名感到困惑。

谢谢!

1 个答案:

答案 0 :(得分:0)

在这里尝试一次。我使用了10分钟的滚动窗口,因此当前值将代表过去10分钟内的任何内容。为了演示起见,我将其更改为 10秒,以便更轻松地验证计算。

逻辑是:

  • 在窗口中过滤出最高20%的最高价格
  • 计算过滤数据的加权平均值(qty_pct之和*价格)
  • 注意:如果我们有1-4 obs,它将使用5-9中的最高值,仍然是最高值(1> 20%),10-14、2 obs(2 > 20%),等等。

编辑:意识到我是在计算最高分位数,而不是观测值的前20%。保留以下原始文档,以及此处的更正版本:

views/tester.hbs

输出

def top_obs_wavg(s):
    ## greater than 20% of obs > valid observation
    if len(s) <  5: # not enought for 20%, keep the largest
        valid_index =s.nlargest(1).index
    else:
        valid_index = s.nlargest(len(s)//5).index ## keep all above 20%

    ## filter pct_qty of tot_qty for the window, only those for top price quantile (>20%)
    pct_qty = df.loc[valid_index,'quantity']/np.sum(df.loc[valid_index,'quantity'])

    ## return the sum of the valid percentages * valid prices > weigthed average.
    return np.sum(pct_qty*s[valid_index])

df['t20_wavg'] = df.rolling('10s')['price'].apply(top_obs_wavg, raw=False)

使用分位数

                       price    quantity    t20_wavg
ts          
2017-12-16 03:02:35.500     6   30          6.000000
2017-12-16 03:02:36.500     9   18          9.000000
2017-12-16 03:02:37.500     7   85          9.000000
2017-12-16 03:02:38.500     3   51          9.000000
2017-12-16 03:02:39.500     6   19          9.000000
2017-12-16 03:02:40.500     4   72          9.000000
2017-12-16 03:02:41.500     6   47          9.000000
2017-12-16 03:02:42.500     2   64          9.000000
2017-12-16 03:02:43.500     8   21          9.000000
2017-12-16 03:02:44.500     6   46          8.461538
2017-12-16 03:02:45.500     5   40          8.461538
2017-12-16 03:02:46.500     8   13          8.000000
2017-12-16 03:02:47.500     2   99          8.000000
2017-12-16 03:02:48.500     8   19          8.000000
2017-12-16 03:02:49.500     6   60          8.000000

然后我们可以使用熊猫滚动类:

def top_quantile_wavg(s):
    ## greater than 20% quantile > valid observation
    is_valid = s >= s.quantile()
    valid_index = s.index[is_valid]

    ## filter pct_qty of tot_qty for the window, only those for top price quantile (>20%)
    pct_qty = df.loc[valid_index,'quantity']/np.sum(df.loc[valid_index,'quantity'])

    ## return the sum of the valid percentages * valid prices > weigthed average.
    return np.sum(pct_qty*s[valid_index])

输出

## change to 10T for 10 minutes
df['t20_wavg'] = df.rolling('10s')['price'].apply(top_quantile_wavg, raw=False)