简体   繁体   English

使用 seaborn 绘制 QQ 图的 FacetGrid

[英]Drawing a FacetGrid of QQ-plots with seaborn

I am unable to draw a FacetGrid of QQ-plots with seaborn .我无法使用seaborn绘制QQ 图FacetGrid

I have a matrix of m rows (observations) and n columns (features), and I want to draw a QQ-plot for each feature (column) to compare it with the normal distribution.我有一个 m 行(观察值)和 n 列(特征)的矩阵,我想为每个特征(列)绘制一个 QQ 图以将其与正态分布进行比较。

So far, my code is like this:到目前为止,我的代码是这样的:

import scipy.stats as ss

def qqplots(fpath, expr, title):

    def quantile_plot(x, **kwargs):
        x = ss.zscore(x)
        qntls, xr = ss.probplot(x, dist="norm")
        plt.scatter(xr, qntls, **kwargs)

    expr_m = pd.melt(expr)
    expr_m.columns = ["Feature", "Value"]
    n_feat = len(expr_m["Feature"].value_counts().index)

    n_cols = int(np.sqrt(n_feat)) + 1

    g = sns.FacetGrid(expr_m, col="Feature", col_wrap=n_cols)
    g.map(quantile_plot, "Value");
    plt.savefig(fpath + ".pdf", bbox_inches="tight")
    plt.savefig(fpath + ".png", bbox_inches="tight")
    plt.close()

qqplots("lognorm_qqplot", np.log2(expr), "Log-normal qqplot")

The expr variable is a pandas DataFrame with m rows (observations) and n columns (features). expr变量是一个 pandas DataFrame,有 m 行(观察值)和 n 列(特征)。

The Exception I get is the following:我得到的异常如下:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-52-f9333a55702e> in <module>()
     39     plt.close()
     40 
---> 41 qqplots("lognorm_qqplot", np.log2(expr), "Log-normal qqplot")

<ipython-input-52-f9333a55702e> in qqplots(fpath, expr, title)
     34 
     35     g = sns.FacetGrid(expr_m, col="Feature", col_wrap=n_cols)
---> 36     g.map(quantile_plot, "Value");
     37     plt.savefig(fpath + ".pdf", bbox_inches="tight")
     38     plt.savefig(fpath + ".png", bbox_inches="tight")

/usr/local/lib/python3.5/site-packages/seaborn/axisgrid.py in map(self, func, *args, **kwargs)
    726 
    727             # Draw the plot
--> 728             self._facet_plot(func, ax, plot_args, kwargs)
    729 
    730         # Finalize the annotations and layout

/usr/local/lib/python3.5/site-packages/seaborn/axisgrid.py in _facet_plot(self, func, ax, plot_args, plot_kwargs)
    810 
    811         # Draw the plot
--> 812         func(*plot_args, **plot_kwargs)
    813 
    814         # Sort out the supporting information

<ipython-input-52-f9333a55702e> in quantile_plot(y, **kwargs)
     25         y = ss.zscore(y)
     26         qntls, xr = ss.probplot(y, dist="norm")
---> 27         plt.scatter(xr, qntls, **kwargs)
     28 
     29     expr_m = pd.melt(expr)

/usr/local/lib/python3.5/site-packages/matplotlib/pyplot.py in scatter(x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, hold, data, **kwargs)
   3249                          vmin=vmin, vmax=vmax, alpha=alpha,
   3250                          linewidths=linewidths, verts=verts,
-> 3251                          edgecolors=edgecolors, data=data, **kwargs)
   3252     finally:
   3253         ax.hold(washold)

/usr/local/lib/python3.5/site-packages/matplotlib/__init__.py in inner(ax, *args, **kwargs)
   1810                     warnings.warn(msg % (label_namer, func.__name__),
   1811                                   RuntimeWarning, stacklevel=2)
-> 1812             return func(ax, *args, **kwargs)
   1813         pre_doc = inner.__doc__
   1814         if pre_doc is None:

/usr/local/lib/python3.5/site-packages/matplotlib/axes/_axes.py in scatter(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, **kwargs)
   3838         y = np.ma.ravel(y)
   3839         if x.size != y.size:
-> 3840             raise ValueError("x and y must be the same size")
   3841 
   3842         s = np.ma.ravel(s)  # This doesn't have to match x, y in size.

ValueError: x and y must be the same size

I achieved this, and also changed the color to use the Seaborn color palette, with the following code: 我做到了这一点,还通过以下代码将颜色更改为使用Seaborn调色板:

def qqplots(fpath, expr, title):

    def quantile_plot(x, **kwargs):
        x = ss.zscore(x)
        ss.probplot(x, plot=plt)

    expr_m = pd.melt(expr)
    expr_m.columns = ["Feature", "Value"]
    n_feat = len(expr_m["Feature"].value_counts().index)

    n_cols = int(np.sqrt(n_feat)) + 1

    g = sns.FacetGrid(expr_m, col="Feature", col_wrap=n_cols)
    g.map(quantile_plot, "Value");
    for ax in g.axes:
        ax.get_lines()[0].set_markerfacecolor(sns.color_palette()[0])
        ax.get_lines()[1].set_color(sns.color_palette()[3])
    plt.savefig(fpath + ".pdf", bbox_inches="tight")
    plt.savefig(fpath + ".png", bbox_inches="tight")
    plt.close()

qqplots("lognorm_qqplot", np.log2(expr), "Log-normal qqplot")

Answering your question: "I am unable to draw a FacetGrid of QQ-plots with seaborn.", I give you here an example with dataset tips from seaborn .回答你的问题:“我无法用 seaborn 绘制 QQ 图的 FacetGrid。”,我在这里给你一个来自seaborn的数据集tips的例子。

To draw qqplots, one of the best approaches is to use the statsmodels library which has the qqplot function built into it.要绘制 qqplots,最好的方法之一是使用内置了qqplot function 的statsmodels库。 This function generates a new figure if the given ax is not passed as an argument.如果给定的ax未作为参数传递,则此 function 会生成一个新图形。 Therefore, using FacetGrid.map() with this function generates individual figures instead of plotting everything on the grid.因此,将FacetGrid.map()与此 function 一起使用会生成单独的图形,而不是在网格上绘制所有内容。 To deal with this, you can use a user-defined function in which sm.qqplots retrieves the current ax thanks to plt.gca() .为了解决这个问题,您可以使用用户定义的 function ,其中sm.qqplots通过plt.gca()检索当前ax Here I created a new function called qqplot_new .在这里,我创建了一个名为qqplot_new Here the qqplots are like test for normality of data.这里的 qqplots 就像测试数据的正态性。

from matplotlib import pyplot as plt
import seaborn as sns
import statsmodels.api as sm

tips = sns.load_dataset("tips")

def qqplot_new(x, ax=None, **kwargs):
    if ax is None:
        ax = plt.gca()
    sm.qqplot(x, ax=ax, **kwargs)
    
g = sns.FacetGrid(tips, col="time",  row="sex")
g.map(qqplot_new, "total_bill", line='s')

Output: Figure obtained Output:得到的图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM