Я столкнулся с проблемой производительности вычислений zscore за 10 лет истории проката (расширения). Это слишком медленно
для одного недавнего дня Zscore, это нужно 17 секунд
для расчета всей истории потребуется около 30 минут. (Я уже пересобрал эту запись истории на недельный уровень, чтобы уменьшить ее до общей записи.
Если вы посоветуете ускорить мою функцию lastz, пожалуйста, не стесняйтесь поделиться своей идеей.
Вот деталь.
1. Набор данных. 10-летняя запись, которая была пересчитана, чтобы сбалансировать размер и точность.
Общий размер (207376, 8)
который охватывает около 500 индексных данных за последние 10 лет. Вот образец:
> Close PB1 PB2 PE1 PE2 TurnoverValue TurnoverVol ROE
>ticker tradeDate
>000001 2007-01-07 2678.526489 3.38135 2.87570 34.423700 61.361549 7.703712e+10 1.131558e+10 0.098227
>2007-01-14 2755.759814 3.45878 3.09090 35.209019 66.407800 7.897185e+10 1.116473e+10 0.098236
>2007-01-21 2796.761572 3.49394 3.31458 35.561800 70.449658 8.416415e+10 1.129387e+10 0.098250
- Я хочу проанализировать изменения в истории и сделать прогноз на будущее.
Итак, функция lastz определена так:
Функции должны ускориться:
ts_start=pd.to_date("20180831")
@numba.jit
def lastz(x):
if x.index.max()[1]<ts_start:
return np.nan
else:
freedom = 1 # it is sample, so the sample std degree of freedome should not be 0 but 1
nlimit_interpolate = int(len(x)/100) #1% fill allowed
#print(nlimit_interpolate, len(x))
x=x.interpolate(limit=nlimit_interpolate+1 ) # plus 1 in case of 0 or minus
x=x.loc[x.notnull()]
Arry=x.values
zscore = stats.zmap(Arry[-1],Arry,ddof=freedom)
return zscore
weekly = weekly.sort_index()
%prun -s cumtime result = weekly.groupby(level="ticker").agg(lastz)
Вот результаты сокращения для одиночного вызова:
13447048 вызовов функций (13340521 примитивных вызовов) за 17,183 секунд
Упорядочено по: совокупному времени
> ncalls tottime percall cumtime percall
> filename:lineno(function)
> 1 0.000 0.000 17.183 17.183 {built-in method builtins.exec}
> 1 0.000 0.000 17.183 17.183 <string>:1(<module>)
> 1 0.000 0.000 17.176 17.176 groupby.py:4652(aggregate)
> 1 0.000 0.000 17.176 17.176 groupby.py:4086(aggregate)
> 1 0.000 0.000 17.176 17.176 base.py:562(_aggregate_multiple_funcs)
> 16/8 0.000 0.000 17.171 2.146 groupby.py:3471(aggregate)
> 8 0.000 0.000 17.171 2.146 groupby.py:3513(_aggregate_multiple_funcs)
> 8 0.000 0.000 17.147 2.143 groupby.py:1060(_python_agg_general)
> 8 0.000 0.000 17.145 2.143 groupby.py:2668(agg_series)
> 8 0.172 0.022 17.145 2.143 groupby.py:2693(_aggregate_series_pure_python)
> 4400 0.066 0.000 15.762 0.004 groupby.py:1062(<lambda>)
> 4400 0.162 0.000 14.255 0.003 <ipython-input-10-fdb784c8abd8>:15(lastz)
> 4400 0.035 0.000 8.982 0.002 base.py:807(max)
> 4400 0.070 0.000 7.955 0.002 multi.py:807(values)
> 4400 0.017 0.000 6.406 0.001 datetimes.py:976(astype)
> 4400 0.007 0.000 6.316 0.001 datetimelike.py:1130(astype)
> 4400 0.030 0.000 6.301 0.001 datetimelike.py:368(_box_values_as_index)
> 4400 0.009 0.000 5.613 0.001 datetimelike.py:362(_box_values)
> 4400 0.860 0.000 5.602 0.001 {pandas._libs.lib.map_infer} 1659008 4.278 0.000 4.741
> 0.000 datetimes.py:606(<lambda>)
> 4328 0.096 0.000 1.774 0.000 generic.py:5980(interpolate)
> 4336 0.015 0.000 1.696 0.000 indexing.py:1463(__getitem__)
> 4328 0.028 0.000 1.675 0.000 indexing.py:1854(_getitem_axis)
Мне было интересно, слишком ли часты вызовы для сравнения времени и данных, и для лучшего способа пропустить вычисленный результат. Я подсчитываю результат еженедельно. Таким образом, данные на прошлой неделе уже нет в наличии для повторного расчета. index.max () [1] использовался для проверки того, что набор данных позже определенного дня. Если новее, рассчитывается, в противном случае просто верните nan.
если я использовал режим прокрутки или расширения, для получения результата потребуется полчаса или 2 часа.
Цените любую идею или подсказку, чтобы ускорить работу функции.