如何加速/向量化计算滚动协方差矩阵的多级迭代?

发布于 2025-01-20 11:18:32 字数 1050 浏览 0 评论 0原文

由于for-loops在Python中的性能不佳,因此我需要加快以下代码。

我尝试的事情:

1。申请。 - 尚未弄清楚如何应用多级DF。

2。 numba。 - 似乎Numba或Bodo不支持Pandas滚动。

代码如下:

df = pd.DataFrame(np.random.randn(9,3),columns=['A','B','C'])
df_result = pd.DataFrame()
shape = np.full(df.shape[1],1)

def func_cov(df):
    df_cov = df.rolling(3,min_periods=3).cov()
    for i in df.index:
        df_result.loc[i,'result'] = np.dot(shape.T,np.dot(df_cov.loc[i], shape))
    return df_result

func_cov(df)


df:
    A   B   C
0   0.191484    0.765756    -1.288696
1   -0.111369   1.276903    1.567775
2   -0.209460   2.920247    0.142898
3   0.169375    1.096265    -0.646460
4   3.847551    0.936200    -1.221572
5   -1.783127   0.426784    1.311940
6   -0.417902   0.253048    0.097059
7   -1.176098   -0.975650   1.481306
8   -1.429595   0.257955    -0.832083


desired df_result:
    result
0   NaN
1   NaN
2   3.258732
3   1.579507
4   2.359369
5   3.684835
6   4.364114
7   0.125943
8   0.981440


Since for-loops have bad performance in python, I need to speed up the following code.

Things I tried:

1. apply. -- Haven't figured out how to apply on multilevel df.

2. Numba. -- Seems Numba or Bodo do not support pandas rolling.

code as below:

df = pd.DataFrame(np.random.randn(9,3),columns=['A','B','C'])
df_result = pd.DataFrame()
shape = np.full(df.shape[1],1)

def func_cov(df):
    df_cov = df.rolling(3,min_periods=3).cov()
    for i in df.index:
        df_result.loc[i,'result'] = np.dot(shape.T,np.dot(df_cov.loc[i], shape))
    return df_result

func_cov(df)


df:
    A   B   C
0   0.191484    0.765756    -1.288696
1   -0.111369   1.276903    1.567775
2   -0.209460   2.920247    0.142898
3   0.169375    1.096265    -0.646460
4   3.847551    0.936200    -1.221572
5   -1.783127   0.426784    1.311940
6   -0.417902   0.253048    0.097059
7   -1.176098   -0.975650   1.481306
8   -1.429595   0.257955    -0.832083


desired df_result:
    result
0   NaN
1   NaN
2   3.258732
3   1.579507
4   2.359369
5   3.684835
6   4.364114
7   0.125943
8   0.981440


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北音执念 2025-01-27 11:18:32

您可以将数据框转换为numpy数组,然后使用NUMBA和基本循环进行所有作业:

import numba as nb

df = pd.DataFrame(np.random.randn(9,3),columns=['A','B','C'])
df_result = pd.DataFrame()
shape = np.full(df.shape[1],1)

@nb.njit('(float64[:,::1], float64[:])')
def fast_func_cov(values, shape):
    result = np.empty(len(values))
    result[0] = result[1] = np.nan
    for i in range(2, len(values)):
        cov_mat = np.cov(values[i-2:i+1,:].T)
        result[i] = np.dot(shape.T,np.dot(cov_mat, shape))
    return result
fast_func_cov(np.ascontiguousarray(df.values), shape.astype(np.float64))

values = np.ascontiguousarray(df.values)
df_result['result'] = fast_func_cov(values, shape.astype(np.float64))

在我的计算机上,计算需要0.016毫秒,而初始计算功能则为7 ms。这大约是 440倍。话虽这么说,大熊猫的分配0.032 ms导致总体代码的速度更快150倍。

You can convert the dataframe to a Numpy array and then do all the job using Numba and basic loops:

import numba as nb

df = pd.DataFrame(np.random.randn(9,3),columns=['A','B','C'])
df_result = pd.DataFrame()
shape = np.full(df.shape[1],1)

@nb.njit('(float64[:,::1], float64[:])')
def fast_func_cov(values, shape):
    result = np.empty(len(values))
    result[0] = result[1] = np.nan
    for i in range(2, len(values)):
        cov_mat = np.cov(values[i-2:i+1,:].T)
        result[i] = np.dot(shape.T,np.dot(cov_mat, shape))
    return result
fast_func_cov(np.ascontiguousarray(df.values), shape.astype(np.float64))

values = np.ascontiguousarray(df.values)
df_result['result'] = fast_func_cov(values, shape.astype(np.float64))

On my machine, the computation takes 0.016 ms compared to to 7 ms for the initial computing function. This is about 440 times faster. That being said, the Pandas assignment 0.032 ms resulting in a 150 times faster code overall.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文