【问题标题】:Is there a function to make scatterplot matrices in matplotlib?matplotlib 中是否有制作散点图矩阵的功能?
【发布时间】:2011-10-29 19:36:41
【问题描述】:

散点图矩阵示例

matplotlib.pyplot中有这样的功能吗?

【问题讨论】:

标签: python matplotlib scatter-plot


【解决方案1】:

对于那些不想定义自己的函数的人,Python中有一个很棒的数据分析库,名为Pandas,可以在其中找到scatter_matrix()方法:

from pandas.plotting import scatter_matrix
df = pd.DataFrame(np.random.randn(1000, 4), columns = ['a', 'b', 'c', 'd'])
scatter_matrix(df, alpha = 0.2, figsize = (6, 6), diagonal = 'kde')

【讨论】:

  • 嗨,为什么只有部分子图有网格?可以修改(全部或全部)?谢谢
  • +1 这将教会我在查看它是否已经在 pandas 中之前搜索 Python 功能。第 1 步:总是问,它是否已经存在于 pandas 中? pd.scatter_matrix(df); plt.show()。难以置信。
  • 在 matplotlib 散点图矩阵中放置一个 kde 是一项极限运动。我喜欢熊猫。
  • 有谁知道pd.tools.plotting.scatter_matrix 的实际API 文档在哪里?我到处都只能找到一个例子——我找不到适合我生活的可选参数......
  • 截至pandas 0.20scatter_matrix 已移至pandas.plotting.scatter_matrix
【解决方案2】:

一般来说,matplotlib 通常不包含对多个坐标区对象(在本例中为子图)进行操作的绘图函数。期望您可以编写一个简单的函数来按照您的意愿将事物串起来。

我不太确定您的数据是什么样的,但是从头开始构建一个函数来执行此操作非常简单。如果您总是要使用结构化或 rec 数组,那么您可以稍微简化一下。 (即,每个数据系列总是有一个名称,因此您可以省略指定名称。)

举个例子:

import itertools
import numpy as np
import matplotlib.pyplot as plt

def main():
    np.random.seed(1977)
    numvars, numdata = 4, 10
    data = 10 * np.random.random((numvars, numdata))
    fig = scatterplot_matrix(data, ['mpg', 'disp', 'drat', 'wt'],
            linestyle='none', marker='o', color='black', mfc='none')
    fig.suptitle('Simple Scatterplot Matrix')
    plt.show()

def scatterplot_matrix(data, names, **kwargs):
    """Plots a scatterplot matrix of subplots.  Each row of "data" is plotted
    against other rows, resulting in a nrows by nrows grid of subplots with the
    diagonal subplots labeled with "names".  Additional keyword arguments are
    passed on to matplotlib's "plot" command. Returns the matplotlib figure
    object containg the subplot grid."""
    numvars, numdata = data.shape
    fig, axes = plt.subplots(nrows=numvars, ncols=numvars, figsize=(8,8))
    fig.subplots_adjust(hspace=0.05, wspace=0.05)

    for ax in axes.flat:
        # Hide all ticks and labels
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)

        # Set up ticks only on one side for the "edge" subplots...
        if ax.is_first_col():
            ax.yaxis.set_ticks_position('left')
        if ax.is_last_col():
            ax.yaxis.set_ticks_position('right')
        if ax.is_first_row():
            ax.xaxis.set_ticks_position('top')
        if ax.is_last_row():
            ax.xaxis.set_ticks_position('bottom')

    # Plot the data.
    for i, j in zip(*np.triu_indices_from(axes, k=1)):
        for x, y in [(i,j), (j,i)]:
            axes[x,y].plot(data[x], data[y], **kwargs)

    # Label the diagonal subplots...
    for i, label in enumerate(names):
        axes[i,i].annotate(label, (0.5, 0.5), xycoords='axes fraction',
                ha='center', va='center')

    # Turn on the proper x or y axes ticks.
    for i, j in zip(range(numvars), itertools.cycle((-1, 0))):
        axes[j,i].xaxis.set_visible(True)
        axes[i,j].yaxis.set_visible(True)

    return fig

main()

【讨论】:

  • 哇,好多新功能!是的,当你掌握了模块并不太难......但不像在 R 中那样调用pairs 那么简单。:)
  • 真的!根据我的(有限!)经验,R 有很多更专业的功能。 Matplotlib 有一种更 DIY 的方法。 (或者,无论如何,专业的统计绘图功能肯定要少得多。)
  • 我当然有这种感觉。我坚持使用 Python 三重奏(目前),希望它提供其他优势......
  • 在我看来,最大的优势是python的灵活性。 R 是一种出色的领域特定语言,如果您只是想做统计分析,它是无与伦比的。 Python 是一种很好的通用编程语言,您将真正开始看到大型程序的好处。一旦你开始想要一个具有交互式 gui 的程序,它可以从 web 中获取数据、解析一些随机的二进制文件格式、进行分析并将其全部绘制出来,一种通用的编程语言就会显示出很多优势。当然,很多语言都是这样,但我更喜欢 python。 :)
  • @Joe Kington,首先,感谢这个例子(我经常使用它)和你所有的其他 mpl 例子!几点: 1. 对于那些希望匹配 R 的人,x 和 y 值是向后的:将 plot axes[x,y] 更改为 axes[y,x]。 2. 在 subplots() 中设置sharex='col', sharey='row' 3. 对角线影响刻度限制,所以要么设置限制,要么绘制axes[i,i].plot(data[i], data[i], linestyle='None') 4. 如果数据是行,列格式,那么输入必须转置,data.T跨度>
【解决方案3】:

你也可以使用Seaborn's pairplot function:

import seaborn as sns
sns.set()
df = sns.load_dataset("iris")
sns.pairplot(df, hue="species")

【讨论】:

  • seaborn 的恼人之处在于它以 pandas 数据帧为中心。如果你有一个 NumPy 数组,这种解决方法会让人觉得烦人,如果你已经有一个 pandas DataFrame,为什么不直接使用 pandas 的内置 scatter_matrix 方法?
  • 不幸的是,它不允许散点图矩阵由两组不同的变量组成。它只是给出了 vars vs vars 图。这使中型和大型数据集的分析变得复杂。
【解决方案4】:

感谢您分享您的代码!你为我们解决了所有困难的事情。在使用它时,我注意到一些看起来不太对劲的小东西。

  1. [FIX #1] 轴抽动没有像我预期的那样排列(即,在您上面的示例中,您应该能够在所有绘图的任何点上绘制一条垂直和水平线,并且线应该穿过其他图中的对应点,但现在不会发生这种情况。

  2. [FIX #2] 如果要绘制的变量数为奇数,则右下角轴不会拉动正确的 xtics 或 ytics。它只是将其保留为默认的 0..1 滴答声。

  3. 不是修复,但我可以选择显式输入 names,以便它在对角位置放置变量 i 的默认 xi

您将在下面找到解决这两点的代码的更新版本,否则会保留代码的美感。

import itertools
import numpy as np
import matplotlib.pyplot as plt

def scatterplot_matrix(data, names=[], **kwargs):
    """
    Plots a scatterplot matrix of subplots.  Each row of "data" is plotted
    against other rows, resulting in a nrows by nrows grid of subplots with the
    diagonal subplots labeled with "names".  Additional keyword arguments are
    passed on to matplotlib's "plot" command. Returns the matplotlib figure
    object containg the subplot grid.
    """
    numvars, numdata = data.shape
    fig, axes = plt.subplots(nrows=numvars, ncols=numvars, figsize=(8,8))
    fig.subplots_adjust(hspace=0.0, wspace=0.0)

    for ax in axes.flat:
        # Hide all ticks and labels
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)

        # Set up ticks only on one side for the "edge" subplots...
        if ax.is_first_col():
            ax.yaxis.set_ticks_position('left')
        if ax.is_last_col():
            ax.yaxis.set_ticks_position('right')
        if ax.is_first_row():
            ax.xaxis.set_ticks_position('top')
        if ax.is_last_row():
            ax.xaxis.set_ticks_position('bottom')

    # Plot the data.
    for i, j in zip(*np.triu_indices_from(axes, k=1)):
        for x, y in [(i,j), (j,i)]:
            # FIX #1: this needed to be changed from ...(data[x], data[y],...)
            axes[x,y].plot(data[y], data[x], **kwargs)

    # Label the diagonal subplots...
    if not names:
        names = ['x'+str(i) for i in range(numvars)]

    for i, label in enumerate(names):
        axes[i,i].annotate(label, (0.5, 0.5), xycoords='axes fraction',
                ha='center', va='center')

    # Turn on the proper x or y axes ticks.
    for i, j in zip(range(numvars), itertools.cycle((-1, 0))):
        axes[j,i].xaxis.set_visible(True)
        axes[i,j].yaxis.set_visible(True)

    # FIX #2: if numvars is odd, the bottom right corner plot doesn't have the
    # correct axes limits, so we pull them from other axes
    if numvars%2:
        xlimits = axes[0,-1].get_xlim()
        ylimits = axes[-1,0].get_ylim()
        axes[-1,-1].set_xlim(xlimits)
        axes[-1,-1].set_ylim(ylimits)

    return fig

if __name__=='__main__':
    np.random.seed(1977)
    numvars, numdata = 4, 10
    data = 10 * np.random.random((numvars, numdata))
    fig = scatterplot_matrix(data, ['mpg', 'disp', 'drat', 'wt'],
            linestyle='none', marker='o', color='black', mfc='none')
    fig.suptitle('Simple Scatterplot Matrix')
    plt.show()

再次感谢您与我们分享此内容。我已经用过很多次了!哦,我重新安排了代码的 main() 部分,这样它就可以是正式的示例代码,或者在被导入另一段代码时不会被调用。

【讨论】:

  • 谢谢,在看到您的回答之前,我一直遇到@Joe Kington 的代码问题。它为我节省了一些调试时间:)
  • 任何想法,我怎样才能让这个函数更快,我需要生成一个大约 100 个变量的大散点图矩阵,这个方法很慢。
【解决方案5】:

在阅读问题时,我希望看到包括rpy 在内的答案。我认为这是一个很好的选择,可以利用两种漂亮的语言。所以这里是:

import rpy
import numpy as np

def main():
    np.random.seed(1977)
    numvars, numdata = 4, 10
    data = 10 * np.random.random((numvars, numdata))
    mpg = data[0,:]
    disp = data[1,:]
    drat = data[2,:]
    wt = data[3,:]
    rpy.set_default_mode(rpy.NO_CONVERSION)

    R_data = rpy.r.data_frame(mpg=mpg,disp=disp,drat=drat,wt=wt)

    # Figure saved as eps
    rpy.r.postscript('pairsPlot.eps')
    rpy.r.pairs(R_data,
       main="Simple Scatterplot Matrix Via RPy")
    rpy.r.dev_off()

    # Figure saved as png
    rpy.r.png('pairsPlot.png')
    rpy.r.pairs(R_data,
       main="Simple Scatterplot Matrix Via RPy")
    rpy.r.dev_off()

    rpy.set_default_mode(rpy.BASIC_CONVERSION)


if __name__ == '__main__': main()

我无法发布图片来显示结果 :( 抱歉!

【讨论】:

    猜你喜欢
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多