【问题标题】:Quickest way to calculate subset of correlation matrix计算相关矩阵子集的最快方法
【发布时间】:2020-05-14 16:44:36
【问题描述】:

我偏爱使用 pandas 内置的 corr 方法来处理数据帧。但是,我正在尝试计算具有 45,000 列的数据帧的相关矩阵。然后重复这个 250 次。计算使我的内存崩溃(16 GB,mac book pro)。我正在获取结果相关矩阵的列的统计信息。所以我需要一列与其他列的相关性来计算这些统计数据。我的解决方案是计算列子集与其他列的相关性,但我需要一种有效的方法来做到这一点。

考虑:

import pandas as pd
import numpy as np

np.random.seed([3,1415])

df = pd.DataFrame(np.random.rand(6, 4), columns=list('ABCD'))
df

我只想计算 ['A', 'B'] 的相关性

corrs = df.corr()[['A', 'B']]
corrs

我将通过计算平均值或其他一些统计数据来完成它。

我无法使用用于创建示例的代码,因为当我扩大规模时,我没有内存。执行计算时,它必须使用与选择的列数成正比的内存量,以计算相对于其他所有内容的相关性。

我正在寻找性能最好的大规模解决方案。我有一个解决方案,但我正在寻找其他想法以确保我得到最好的。任何提供的答案只要返回演示中所示的正确答案并满足内存限制,我都会点赞(我也鼓励彼此点赞)。

下面是我的代码:

def corr(df, k=0, l=10):
    d = df.values - df.values.mean(0)
    d_ = d[:, k:l]
    s = d.std(0, keepdims=True)
    return pd.DataFrame(d.T.dot(d[:, k:l]) / s.T.dot(s[:, k:l]) / d.shape[0],
                        df.columns, df.columns[k:l])   

【问题讨论】:

    标签: python numpy pandas


    【解决方案1】:

    使用点积计算相关性(如您的示例所示)似乎是一种好方法。我将描述两个改进,然后是实现它们的代码。

    改进1:拉出点积的意思

    我们可以从点积中提取均值,以避免必须从每个值中减去它们(类似于您如何从点积中提取标准差,我们也会这样做)。

    x, y 成为带有n 元素的向量。让a, b 成为标量。让<x,y> 表示 x 和 y 之间的点积。

    xy之间的相关性可以用点积来表示

    <(x-mean(x))/std(x), (y-mean(y))/std(y)> / n
    

    要从点积中提取标准差,我们可以使用以下恒等式(如您在上面所做的):

    <ax, by> = a*b*<x, y>
    

    为了从点积中提取手段,我们可以推导出另一个身份:

    <x+a, y+b> = <x,y> + a*sum(y) + b*sum(x) + a*b*n
    

    a = -mean(x), b = -mean(y) 的情况下,这简化为:

    <x-mean(x), y-mean(y)> = <x, y> - sum(x)*sum(y)/n
    

    使用这些身份,xy 之间的相关性相当于:

    (<x, y> - sum(x)*sum(y)/n) / (std(x)*std(y)*n)
    

    在下面的函数中,这将使用矩阵乘法和外积来表示,以同时处理多个变量(如您的示例所示)。

    改进 2:预计算总和和标准差

    我们可以预先计算总和和标准差,以避免每次调用函数时对所有列重新计算它们。

    代码

    将这两个改进放在一起,我们有以下几点(我不会说 pandas,所以它是 numpy 的):

    def corr_cols(x, xsum, xstd, lo, hi):
        n = x.shape[0]
    
        return (
            (np.dot(x.T, x[:, lo:hi]) - np.outer(xsum, xsum[lo:hi])/n)
            / (np.outer(xstd, xstd[lo:hi])*n)
        )
    
    # fake data w/ 10 points, 5 dimensions
    x = np.random.rand(10, 5)
    
    # precompute sums and standard deviations along each dimension
    xsum = np.sum(x, 0)
    xstd = np.std(x, 0)
    
    # calculate columns of correlation matrix for dimensions 1 thru 3
    r = corr_cols(x, xsum, xstd, 1, 4)
    

    更好的代码

    预计算和存储总和和标准差可以隐藏在闭包中,以提供更好的界面并保持主代码更简洁。功能上,操作和前面的代码是等价的。

    def col_correlator(x):
        n = x.shape[0]
        xsum = np.sum(x, 0)
        xstd = np.std(x, 0)
    
        return lambda lo, hi: (
            (np.dot(x.T, x[:, lo:hi]) - np.outer(xsum, xsum[lo:hi])/n)
            / (np.outer(xstd, xstd[lo:hi])*n)
        )
    
    # construct function to compute columns of correlation matrix
    cc = col_correlator(x)
    
    # compute columns of correlation matrix for dimensions 1 thru 3
    r = cc(1, 4)
    

    编辑:(piRsquared)

    我想把我的编辑放在这篇文章中,以进一步鼓励对这个答案的支持。

    这是我利用这个建议实现的代码。此解决方案在 pandas 和 numpy 之间来回转换。

    def corr_closure(df):
        d = df.values
        sums = d.sum(0, keepdims=True)
        stds = d.std(0, keepdims=True)
        n = d.shape[0]
    
        def corr(k=0, l=10):
            d2 = d.T.dot(d[:, k:l])
            sums2 = sums.T.dot(sums[:, k:l])
            stds2 = stds.T.dot(stds[:, k:l])
    
            return pd.DataFrame((d2 - sums2 / n) / stds2 / n,
                                df.columns, df.columns[k:l])
    
        return corr
    

    用例:

    corr = corr_closure(df)
    
    corr(0, 2)
    

    【讨论】:

    • 你太棒了。我稍后会验证并做出相应的选择。
    • 已验证!我鼓励任何阅读此答案的人投票并告诉您的朋友投票。在一篇文章中,我了解了如何从相关计算中提取均值,建议进行预计算,以及大量使用闭包。都解释得很好。
    【解决方案2】:

    归功于@user20160,@piRsquared。

    我有一个非常相似的问题。我试图只计算矩阵的四分之一:一组列与另一列之间的相关性。

    我稍微修改了代码,它需要 4 个参数,用于 2 组向量:

    def col_correlator(x):
    n = x.shape[0]
    xsum = np.sum(x, 0)
    xstd = np.std(x, 0)
    
    return lambda lo_c, hi_c, lo_r, hi_r: (
        (np.dot(x[:, lo_r:hi_r].T, x[:, lo_c:hi_c]) - np.outer(xsum[lo_r:hi_r], xsum[lo_c:hi_c]) / n)
        / (np.outer(xstd[lo_r:hi_r], xstd[lo_c:hi_c]) * n)
    )
    
    # construct function to compute columns of correlation matrix
    cc = col_correlator(x)
    
    # compute columns of correlation matrix for dimensions 1 thru 3
    r = cc(n, m,0,n)
    

    【讨论】:

    • 很难相信这个问答已经快 4 年了。
    • 没有。你的评论让我想起了这个问题。我记得我在处理这个问题,感觉不像是 4 年前。
    猜你喜欢
    • 2016-09-26
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 2018-04-14
    相关资源
    最近更新 更多