熊猫在行上迭代以进行特征计算

时间:2019-12-13 20:29:27

标签: python pandas performance iteration

我有一个熊猫数据框,我想基于一些short_windowlong_windowbins值来计算一些特征。更具体地说,对于每个不同的行,我想计算一些特征。为此,我将df_long = df.loc[row:long_window+row]向前移动了一行,例如在第一次迭代中,row=0的熊猫数据帧将为df_long = df.loc[0:50+0],并将根据此数据计算一些特征帧,则row=1将是df_long = df.loc[1:50+1],其他一些特征将被计算并继续。

from numpy.random import seed
from numpy.random import randint
import pandas as pd
from joblib import Parallel, delayed

bins = 12
short_window = 10
long_window = 50

# seed random number generator
seed(1)

price = pd.DataFrame({
    'DATE_TIME': pd.date_range('2012-01-01', '2012-02-01', freq='30min'),
    'value': randint(2, 20, 1489),
    'amount': randint(50, 200, 1489)
})


def vap(row, df, short_window, long_window, bins):

    df_long = df.loc[row:long_window+row]
    df_short = df_long.tail(short_window)

    binning = pd.cut(df_long['value'], bins, retbins=True)[1]
    group_months = pd.DataFrame(df_short['amount'].groupby(pd.cut(df_short['value'], binning)).sum())

    return group_months['amount'].tolist(),  df.loc[long_window + row + 1, 'DATE_TIME']


def feature_extraction(data, short_window, long_window, bins):

    # Vap feature extraction
    ls = [f"feature{row + 1}" for row in range(bins)]
    amount, date = zip(*Parallel(n_jobs=4)(delayed(vap)(i, data, short_window, long_window, bins)
                                                for i in range(0, data.shape[0] - long_window - 1)))
    temp = pd.DataFrame(date, columns=['DATE_TIME'])
    temp[ls] = pd.DataFrame(amount, index=temp.index)
    data = data.merge(temp, on='DATE_TIME', how='outer')

    return data


df = feature_extraction(price, short_window, long_window, bins)

为了节省时间,我尝试并行运行它,但是由于我的数据量大,需要很长时间才能完成。

是否有任何方法可以更改此迭代过程(df_long = df.loc[row:long_window+row])以降低计算成本?我想知道是否有任何方法可以使用pandas.rolling,但是我不确定在这种情况下如何使用它。

任何帮助将不胜感激! 谢谢

1 个答案:

答案 0 :(得分:0)

这是第一次尝试加快计算速度。我检查了前100行,发现binning变量始终相同。所以我设法用固定的垃圾箱做一个高效的算法。但是,当我检查整个数据的功能时,我发现1489中大约有100行,它们具有不同的装箱变量,因此下面的解决方案与原始答案有100行的差异。

基准化:
我的快速功能:28毫秒
我的精确功能:388毫秒
原始功能:12200毫秒
因此,快速功能的速度提高了约500倍,精确功能的速度提高了20倍

快速功能代码:

def feature_extraction2(data, short_window, long_window, bins):
    ls = [f"feature{row + 1}" for row in range(bins)]
    binning = pd.cut([2,19], bins, retbins=True)[1]
    bin_group = np.digitize(data['value'], binning, right=True)
    l_sum = []
    for i in range(1, bins+1):
        sum1 = ((bin_group == i)*data['amount']).rolling(short_window).sum()
        l_sum.append(sum1)

    ar_sum = np.array(l_sum).T
    ar_shifted = np.empty_like(ar_sum)
    ar_shifted[:long_window+1,:] = np.nan
    ar_shifted[long_window+1:,:] = ar_sum[long_window:-1,:]    
    temp = pd.DataFrame(ar_shifted, columns = ls)
    data = pd.concat([data,temp], axis = 1, sort = False)
    return data

精确功能:

data = price.copy()
# Vap feature extraction
ls = [f"feature{row + 1}" for row in range(bins)]
data.shape[0] - long_window - 1)))
norm_volume = []
date = []
for i in range(0, data.shape[0] - long_window - 1):
    row = i
    df = data
    df_long = df.loc[row:long_window+row]
    df_short = df_long.tail(short_window)

    binning = pd.cut(df_long['value'], bins, retbins=True)[1]
    group_months = df_short['amount'].groupby(pd.cut(df_short['value'], binning)).sum().values

    x,y = group_months,  df.loc[long_window + row + 1, 'DATE_TIME']
    norm_volume.append(x)
    date.append(y)

temp = pd.DataFrame(date, columns=['DATE_TIME'])
temp[ls] = pd.DataFrame(norm_volume, index=temp.index)
data = data.merge(temp, on='DATE_TIME', how='outer')