如何将相关矩阵绘制为一组椭圆,类似于 R 露天包?

How can I plot a correlation matrix as a set of ellipses, similar to the R open-air package?

下图是使用open-air R包绘制的:

我知道 matplotlib 有 plt.matshow 函数,
但不能同时清楚地显示变量之间的关系。

这是我早期的作品:

df 是一个包含 7 个变量的 pandas 数据框,如下所示:

我不知道如何将 .csv 文件附加到 Whosebug。

使用plt.matshow(df.corr(),cmap = plt.cm.Greens),如图所示:

第二张图不能像第一张图那样清楚地表示变量的相关关系

编辑:

我将 csv 文件上传到 Google 文档 here

假设你对显示集群关系感兴趣,评论中提到的seaborn包也有一个clustermap。使用相关矩阵(看起来你想在 [-100, 100] 范围内将相关系数显示为 int,你可以执行以下操作:

corr = df.corr().mul(100).astype(int)

     GX   HG   RM   SJ   XB   XN   ZG
GX  100   77   62   71   48   66   57
HG   77  100   69   74   61   61   58
RM   62   69  100   75   48   64   68
SJ   71   74   75  100   50   70   65
XB   48   61   48   50  100   46   51
XN   66   61   64   70   46  100   75
ZG   57   58   68   65   51   75  100

然后使用seaborn.clustermap()如下:

import seaborn as sns
sns.clustermap(data=corr, annot=True, fmt='d', cmap='Greens').savefig('cluster.png')

我不知道有任何现有的 Python 库可以执行这些 "ellipse plots",但使用 matplotlib.collections.EllipseCollection:

实现起来并不是特别困难
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.collections import EllipseCollection

def plot_corr_ellipses(data, ax=None, **kwargs):

    M = np.array(data)
    if not M.ndim == 2:
        raise ValueError('data must be a 2D array')
    if ax is None:
        fig, ax = plt.subplots(1, 1, subplot_kw={'aspect':'equal'})
        ax.set_xlim(-0.5, M.shape[1] - 0.5)
        ax.set_ylim(-0.5, M.shape[0] - 0.5)

    # xy locations of each ellipse center
    xy = np.indices(M.shape)[::-1].reshape(2, -1).T

    # set the relative sizes of the major/minor axes according to the strength of
    # the positive/negative correlation
    w = np.ones_like(M).ravel()
    h = 1 - np.abs(M).ravel()
    a = 45 * np.sign(M).ravel()

    ec = EllipseCollection(widths=w, heights=h, angles=a, units='x', offsets=xy,
                           transOffset=ax.transData, array=M.ravel(), **kwargs)
    ax.add_collection(ec)

    # if data is a DataFrame, use the row/column names as tick labels
    if isinstance(data, pd.DataFrame):
        ax.set_xticks(np.arange(M.shape[1]))
        ax.set_xticklabels(data.columns, rotation=90)
        ax.set_yticks(np.arange(M.shape[0]))
        ax.set_yticklabels(data.index)

    return ec

例如,使用您的数据:

data = df.corr()
fig, ax = plt.subplots(1, 1)
m = plot_corr_ellipses(data, ax=ax, cmap='Greens')
cb = fig.colorbar(m)
cb.set_label('Correlation coefficient')
ax.margins(0.1)

负相关可以绘制为相反方向的椭圆:

fig2, ax2 = plt.subplots(1, 1)
data2 = np.linspace(-1, 1, 9).reshape(3, 3)
m2 = plot_corr_ellipses(data2, ax=ax2, cmap='seismic', clim=[-1, 1])
cb2 = fig2.colorbar(m2)
ax2.margins(0.3)

我今天才发现这个 Python 包 biokit。它提供了一个非常方便的功能来创建各种相关图表。例如:

In [1]: import pandas as pd

In [2]: import matplotlib.pyplot as plt
   ...: from biokit.viz import corrplot

In [6]: corr
Out[6]: 
      GX    HG    RM    SJ    XB    XN    ZG
GX  1.00 -0.77  0.62  0.71  0.48  0.66  0.57
HG -0.77  1.00  0.69  0.74  0.61  0.61  0.58
RM  0.62  0.69  1.00  0.75  0.48  0.64  0.68
SJ  0.71  0.74  0.75  1.00  0.50  0.70  0.65
XB  0.48  0.61  0.48  0.50  1.00 -0.46  0.51
XN  0.66  0.61  0.64  0.70 -0.46  1.00  0.75
ZG  0.57  0.58  0.68  0.65  0.51  0.75  1.00

我拿了Stefan的数据,稍微修改了一下。让我们假设这是一个相关矩阵。现在要创建相关图表,您可以简单地这样做:

In [7]: c = corrplot.Corrplot(corr)
   ...: c.plot()

Correlation chart with ellipses

您可以阅读更多示例here