【问题标题】:Returning the highest and lowest correlations from a correlation matrix in pandas从熊猫中的相关矩阵返回最高和最低相关性
【发布时间】:2019-04-17 14:37:44
【问题描述】:

我有一堆股票数据,我正在尝试构建一个数据框,从相关矩阵中获取前两个股票和底部股票,以及它们的实际相关性。

假设矩阵,corr 看起来像这样:

  A    B    C    D    E
A 1.00 0.65 0.31 0.94 0.55
B 0.87 1.00 0.96 0.67 0.41
C 0.95 0.88 1.00 0.72 0.69
D 0.64 0.84 0.99 1.00 0.78
E 0.71 0.62 0.89 0.32 1.00

我想要做的是能够返回股票 A、B、C、D 和 E 的最好的两只、相关性最低的股票及其相关性,同时降低每只股票明显的 1.00 相关性自己。

生成的数据框或最容易显示的数据框如下所示:

Stock 1st 1st_Val 2nd 2nd_Val Last Last_Val
A     D   0.94    B   0.65    C    0.31
B     C   0.96    A   0.87    E    0.41
C     A   0.95    B   0.88    E    0.69
D     C   0.99    B   0.84    A    0.64
E     C   0.89    A   0.71    D    0.32

到目前为止,通过我的尝试,我已经能够使用corr[stock].nlargest().index[0:].tolist() 查看并返回相关股票名称,然后从每个列表中获取[1][2][-1] 并将它们粘贴到字典中,然后从那里构建数据框。但我无法返回相关值,而且我怀疑我并没有以最有效的方式执行此操作。

任何帮助都非常感谢,干杯

【问题讨论】:

  • 相关矩阵不应该是对称的吗?还是您给定的示例只是示例矩阵?
  • 相关矩阵可以是不对称的,在财务数据中很常见
  • @Gio 相关矩阵永远不能不对称。来自wikipedia因为第 i 个随机变量与第 j 个随机变量的协方差与第 j 个随机变量与第 i 个随机变量的协方差是一回事,每个协方差矩阵是对称的我知道这适用于协方差矩阵,但同样适用。
  • @pault 找不到我想到的论文,但这里有其他作品(被引用很多,所以我认为值得信赖)paper1paper2。另一个例子是价格波动与价格变动的相关性。对于给定的价格 (P) 变化,如果 P 的符号为负,则波动率上升得更多。 (即,给定一只价值为X 的股票,如果股票下跌 10 美元,它会比同一只股票上涨 10 美元增加更多的波动性)

标签: python pandas correlation


【解决方案1】:

您的条件很难概括为一个命令,但这是您可以采用的一种方法。

去掉对角线

import numpy as np
np.fill_diagonal(corr.values, np.nan)
print(corr)
#      A     B     C     D     E
#A   NaN  0.65  0.31  0.94  0.55
#B  0.87   NaN  0.96  0.67  0.41
#C  0.95  0.88   NaN  0.72  0.69
#D  0.64  0.84  0.99   NaN  0.78
#E  0.71  0.62  0.89  0.32   NaN

查找顶部 2 和底部的列名称

您可以使用Find names of top-n highest-value columns in each pandas dataframe row 上的答案来获取每一行(Stock)的前 2 个和后一个值。

order_top2 = np.argsort(-corr.values, axis=1)[:, :2]
order_bottom = np.argsort(corr.values, axis=1)[:, :1]

result_top2 = pd.DataFrame(
    corr.columns[order_top2], 
    columns=['1st', '2nd'],
    index=corr.index
)

result_bottom = pd.DataFrame(
    corr.columns[order_bottom], 
    columns=['Last'],
    index=corr.index
)

result = result_top2.join(result_bottom)
#  1st 2nd Last
#A   D   B    C
#B   C   A    E
#C   A   B    E
#D   C   B    A
#E   C   A    D

现在使用pandas.DataFrame.lookupresult中的每一列获取corr中对应的列值

for x in result.columns:
    result[x+"_Val"] = corr.lookup(corr.index, result[x])
print(result)
#  1st 2nd Last  1st_Val  2nd_Val  Last_Val
#A   D   B    C     0.94     0.65      0.31
#B   C   A    E     0.96     0.87      0.41
#C   A   B    E     0.95     0.88      0.69
#D   C   B    A     0.99     0.84      0.64
#E   C   A    D     0.89     0.71      0.32

重新排序列(可选)

print(result[['1st', '1st_Val', '2nd', '2nd_Val', 'Last', 'Last_Val']])
#  1st  1st_Val 2nd  2nd_Val Last  Last_Val
#A   D     0.94   B     0.65    C      0.31
#B   C     0.96   A     0.87    E      0.41
#C   A     0.95   B     0.88    E      0.69
#D   C     0.99   B     0.84    A      0.64
#E   C     0.89   A     0.71    D      0.32

【讨论】:

    【解决方案2】:

    如果您需要将结果可视化,但实际上并不需要获取和使用实际的相关值,那么为什么不使用非常简单的heatmap?您还可以使用绘图来在每个方格上显示数字。

    import seaborn as sns
    import pandas as pd
    
     dict = {'Date':['2018-01-01','2018-01-02','2018-01-03','2018-01-04','2018-01-05'],'Col1':[1,2,3,4,5],'Col2':[1.1,1.2,1.3,1.4,1.5],'Col3':[0.33,0.98,1.54,0.01,0.99],'Col4':[8,9.98,6,0.01,0.1],'Col1':[19,42,3,0.4,51]}
    df = pd.DataFrame(dict, columns=dict.keys())
    sns.heatmap(df.corr())
    

    【讨论】:

    • 嗨,兄弟,抱歉,快速提问,sns.heatmap(df.corr()) 实际上并没有为我做任何事情,因为我没有使用 jypiter,我只是在 pycharm 上,我需要做 .show() 还是什么?只是看不到要显示热图,干杯
    • @topbantz 你很可能有解决方案here
    • 一直在尝试 sns.plt.show(),结果我只需要 plt.show() 谢谢队友
    【解决方案3】:

    一个不同的答案更多地依赖于modern pandas style。对于第二大相关性,我没有找到好的解决方案。找到答案后我会编辑答案。

    ### Create an example df
    df = pd.DataFrame(data = {"A":pd.np.random.randn(10),
                        "B":pd.np.random.randn(10),
                        "C":pd.np.random.randn(10),
                        "D":pd.np.random.randn(10),
                            }
                    )
    
    
    # Solution
    (
    df.corr() #correlation matrix
      .replace(1, pd.np.nan) # replace the matrix with nans
      .assign(  # assign new variables
                First = lambda x: x.loc[["A","B","C","D"], ["A","B","C","D"]].idxmax(axis = 1), # Biggest correlation idx
                First_value = lambda x: x.loc[["A","B","C","D"], ["A","B","C","D"]].max(axis = 1), # Biggest correlation
                Last = lambda x: x.loc[["A","B","C","D"],["A","B","C","D"]].idxmin(axis = 1), # Smallest correlation idx
                Last_value = lambda x: x.loc[["A","B","C","D"],["A","B","C","D"]].idxmin(axis = 1), # Smallest correlation
                  )
    )
    
    

    我使用.loc[["A","B","C","D"],["A","B","C","D"]] 以便仅对未修改的数据帧进行操作。

    输出:
              A         B         C         D First  First_value Last Last_value
    A       NaN -0.085776 -0.203110 -0.003450     D    -0.003450    C          C
    B -0.085776       NaN -0.110402  0.687283     D     0.687283    C          C
    C -0.203110 -0.110402       NaN  0.017644     D     0.017644    A          A
    D -0.003450  0.687283  0.017644       NaN     B     0.687283    A          A
    

    【讨论】:

    • Last_value 的输入有误。你怎么能扩展它以获得第二高的价值? replace(1, np.nan) 还假设没有两个变量是 100% 相关的(即假设没有非对角线 1)。
    【解决方案4】:

    corr.unstack().min() -> 求值

    corr.unstack().idxmin() -> 查找索引

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-20
      • 2016-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-26
      • 2022-11-14
      相关资源
      最近更新 更多