Предположим, у меня есть DataFrame, на котором я хочу вычислить скользящие или расширяющиеся корреляции Пирсона между двумя столбцами.
import numpy as np
import pandas as pd
import scipy.stats as st
df = pd.DataFrame({'x': np.random.rand(10000), 'y': np.random.rand(10000)})
Со встроенной функциональностью pandas
это очень быстро рассчитать
expanding_corr = df['x'].expanding(50).corr(df['y'])
rolling_corr = df['x'].rolling(50).corr(df['y'])
Однако, если я хочу получить p-значения, связанные с этими корреляциями, лучшее, что я могу сделать, это определить пользовательскую функцию groupby
и передать apply
к объекту groupby
def custom_roll(df, w, **kwargs):
v = df.values
d0, d1 = v.shape
s0, s1 = v.strides
a = np.lib.stride_tricks.as_strided(v, (d0 - (w - 1), w, d1), (s0, s0, s1))
rolled_df = pd.concat({
row: pd.DataFrame(values, columns=df.columns)
for row, values in zip(df.index[(w-1):], a)
})
return rolled_df.groupby(level=0, **kwargs)
c_df = custom_roll(df, 50).apply(lambda df: st.pearsonr(df['x'], df['y']))
Теперь c_df
содержит соответствующие корреляции и, что важно, связанные с ними p-значения.
Однако этот метод чрезвычайно медленный по сравнению со встроенным методом pandas
, что означает, что он не подходит, так как практически я вычисляю эти корреляции тысячи раз в процессе оптимизации. Кроме того, я не уверен, как расширить функцию custom_roll
для расширения окон.
Кто-нибудь может указать мне в направлении использования numpy
чтобы получить p-значения по сравнению с расширяющимися окнами на векторизованных скоростях?