在python中快速计算协方差矩阵,并进行一些小的自定义



我有一个pandas数据帧,我试图找到每列百分比变化的协方差。对于每一对,我希望删除缺少值的行,然后计算百分比。也就是说,我想要这样的东西:

import pandas as pd
import numpy as np
# create dataframe example
N_ROWS, N_COLS = 249, 3535
df = pd.DataFrame(np.random.random((N_ROWS, N_COLS)))
df.iloc[np.random.choice(N_ROWS, N_COLS), np.random.choice(10, 50)] = np.nan
cov_df = pd.DataFrame(index=df.columns, columns=df.columns)
for col_i in df:
for col_j in df:
cov = df[[col_i, col_j]].dropna(how='any', axis=0).pct_change().cov()
cov_df.loc[col_i, col_j] = cov.iloc[0, 1]

问题是这太慢了。下面的代码给了我类似(但不完全(我想要的结果,但它运行得很快

df.dropna(how='any', axis=0).pct_change().cov()

我不知道为什么第二个跑得这么快。我想先加快我的代码,但我不知道怎么做。

我尝试过使用itertools中的combinations来避免重复(col_i, col_j)(col_j, col_i)的计算,并使用multiprocessing中的map来并行计算,但90多分钟后仍未完成。

不知何故,这足够快,尽管我不确定的原因

from scipy.stats import pearsonr
corr = np.zeros((x.shape[1], x.shape[1]))
for i in range(x.shape[1]):
for j in range (i + 1, x.shape[1]):
y = x[:, [i, j]]
y = y[~np.isnan(y).any(axis=1)]
y = np.diff(y, axis=0) / y[:-1, :]
if len(y) < 2:
corr[i, j] = np.nan
continue
y = pearsonr(y[:, 0], y[:, 1])[0]
corr[i, j] = y
corr = corr + corr.T
np.fill_diagonal(corr, 1)

这只需要8分钟,对于我的用例来说已经足够快了。

另一方面,这已经运行了30分钟,但仍未完成。

corr = pd.DataFrame(index=nav.columns, columns=nav.columns)
for col_i in df:
for col_j in df:
corr_ij = df[[col_i, col_j]].dropna(how='any', axis=0).pct_change().corr().iloc[0, 1]
corr.loc[col_i, col_j] = corr_ij
t1 = time.time()

不知道为什么,但无论如何,第一个对我来说已经足够好了。

最新更新