python数据可视化(五) seaborn

绘制网格数据

终于忙完了各种大作业和期末考试。。我活着回来了。。。

当你探索一个中等维度的数据集时,一个非常有用的手段是在一个大图中绘制多个由不同子集构成的子图,这种方式有时被称为“lattice” 或者“trellis”画图法,它来源于small multiples思想。这种方法允许观察者从复杂数据中提取大量的信息,Matplotlib对多轴图像提供了很好的支持,seaborn建立在此之上,直接将图像结构连接到数据结构之上。
使用这个功能你的数据要是pd.dataframe的格式,它必须是 Hadley Whickam所称呼的tidy data的数据格式。简而言之,你的数据必须每一行是一个观测,每一列是一个变量。
对于前几章提到的功能,你基本都可以运用本章所讨论的对象,这将提供极大的灵活性。一些seaborn函数(lmplot,factorplot,pairplot)相当于在函数中“集成”这些功能。与其他子图等级函数不同

子图等级函数并不会创建新的画布(figure)而是在原有axes上画图。

这些(括号里的)高等级函数在调用时,会创建一个全新的画布,当他们被调用时,参数的要求会更为严格,在某些情况下,对于这些函数或其依赖的类的构造函数的参数将提供与图形大小不同的接口属性,如lmplot的情况,您可以在其中设置每个方面的高度和纵横比而不是整体尺寸。使用这些对象之一的任何函数总是在绘制之后返回,而且这些对象中的大多数都具有方便的方法来改变绘制,通常以更抽象和简单的方式。

%matplotlib inline
import numpy as np
import pandas as pd
import seaborn as sns
from scipy import stats
import matplotlib as mpl
import matplotlib.pyplot as plt
sns.set(style="ticks")
np.random.seed(sum(map(ord, "axis_grids")))

Plotting small multiples of data subsets

当你想要在原数据的子集(groupby思想)中独立的绘制一个变量的分布或者多个变量之间的关系时FacetGrid类变得非常有用。一个FacetGrid具有三维:row,col,hue前两个非常明显的代表着坐标轴,可以将hue当做深度,即第三条轴,不同水平由颜色表示。
当FacetGrid对象被dataframe和相应的row column hue参数初始化时,这个类被调用。这些参数变量应该属分类变量。相当于将数据集grouby标记为不同的facet,用于画图。
另外,lmplot()和factorplot函数,在内部调用了该对象,完成后返回。所以其结果可以进一步调整。

tips = sns.load_dataset("tips")
g = sns.FacetGrid(tips, col="time")


这样初始化网格(grid)会建立matplotlb画布(figure)和子图(axes),但是不会画任何东西。
在网格(grid)上可视化数据最常用的方法是FacetGrid.map(),向其传入画图函数,自变量,因变量等。

g = sns.FacetGrid(tips, col="time")
g.map(plt.hist, "tip");


这个函数会画出图像并标出坐标轴,爽吧!一步到位。你也可以提供关键字参数,将其传递给画图函数。

g = sns.FacetGrid(tips, col="sex", hue="smoker")
g.map(plt.scatter, "total_bill", "tip", alpha=.7)
g.add_legend();


还有好多控制网格样子的参数可以传递给类的构造器(sns.FacetGrid)。

g = sns.FacetGrid(tips, row="smoker", col="time", margin_titles=True)
g.map(sns.regplot, "size", "total_bill", color=".3", fit_reg=False, x_jitter=.1);


请注意 margin_titles并没有被matplotlib API正式支持,可能有时并不能正常工作,尤其当图外有图例是不能共存。
图像的高度由每个网格的高度和恨总比决定:

g = sns.FacetGrid(tips, col="day", size=4, aspect=.5)
g.map(sns.barplot, "sex", "total_bill");


如果你的matplotlib版本>1.4,你可以传入使用在gridspec模块中的参数。这可以允许你通过增大某一网格大小的方法来强调这一图片。这在子集数据量不均衡是非常有用(数据量大的组,你就让图片大一点)。

titanic = sns.load_dataset("titanic")
titanic = titanic.assign(deck=titanic.deck.astype(object).sort_values("deck")
g = sns.FacetGrid(titanic, col="class", sharex=False,
                  gridspec_kws={"width_ratios": [5, 3, 3]})
g.map(sns.boxplot, "deck", "age");


网格的默认顺序是从数据信息中衍生出来的, If the variable used to define facets has a categorical type, then the order of the categories is used,除此之外,网格的顺序由类别出现的先后顺序为准。当然,你可以用*_order参数来定义顺序。

ordered_days = tips.day.value_counts().index
g = sns.FacetGrid(tips, row="day", row_order=ordered_days,
                  size=1.7, aspect=4,)
g.map(sns.distplot, "total_bill", hist=False, rug=True);


任何seaborn调色板(可以传给color_palette()的参数)也都可以使用,你也可以传入一个标注了颜色的字典,来标注不同hue属性的数据。

pal = dict(Lunch="seagreen", Dinner="gray")
g = sns.FacetGrid(tips, hue="time", palette=pal, size=5)
g.map(plt.scatter, "total_bill", "tip", s=50, alpha=.7, linewidth=.5, edgecolor="white")
g.add_legend();


你也可以改变他们的形状,通过传入hue_kws参数(字典的方式),这样会使图片在黑白打印的时候更具有辨识性。

g = sns.FacetGrid(tips, hue="sex", palette="Set1", size=5, hue_kws={"marker": ["^", "v"]})
g.map(plt.scatter, "total_bill", "tip", s=100, linewidth=.5, edgecolor="white")
g.add_legend();


当数据维度太高时,你就不能将网格排列在同一行上,这时你可以采用col_wrap,将网格分行,这种情况下,你就不能使用row参数了。(采用col即没列不同,但是维数太高,就用col_wrap折成行)

attend = sns.load_dataset("attention").query("subject <= 12")
g = sns.FacetGrid(attend, col="subject", col_wrap=4, size=2, ylim=(0, 10))
g.map(sns.pointplot, "solutions", "score", color=".3", ci=None);


当你用FacetGrid.map()画图时,你可能需要对图片进行一定的调整,FacetGrid对象拥有一些这样的方法进行操作。最常用的就是FacetGrid.set(),还有一些更加专门的方法比如FacetGrid.set_axis_labels()它设定内部的网格没有轴标签。

with sns.axes_style("white"):
    g = sns.FacetGrid(tips, row="sex", col="smoker", margin_titles=True, size=2.5)
g.map(plt.scatter, "total_bill", "tip", color="#334488", edgecolor="white", lw=.5);
g.set_axis_labels("Total bill (US Dollars)", "Tip");
g.set(xticks=[10, 30, 50], yticks=[2, 6, 10]);
g.fig.subplots_adjust(wspace=.02, hspace=.02);


更加深度的订制,可以通过直接调节底层的matplotlib FigureAxes对象来实现。它们被以2维数组的形式储存在图的fig 与axes成员中。 当没有行或列面的网格时,还可以使用ax属性直接访问单个轴。

g = sns.FacetGrid(tips, col="smoker", margin_titles=True, size=4)
g.map(plt.scatter, "total_bill", "tip", color="#338844", edgecolor="white", s=50, lw=1)
for ax in g.axes.flat:
    ax.plot((0, 50), (0, .2 * 50), c=".2", ls="--")
g.set(xlim=(0, 60), ylim=(0, 14));

对网格map自定义函数

当你使用FacetGrid画图时,并不用局限于现有的matplotlib和seaborn函数。但是自定义函数想要正常工作,就要遵循下面的准则。
1. 绘制对象必须是当前活动的子图, 这对matplotlib.pyplot命名空间中的函数是正确的,如果要使用其方法,可以调用plt.gca来获取对当前Axes的直接引用。
2. 它必须接受它在位置参数中绘制的数据。 在内部,FacetGrid将传递一系列针对传递给FacetGrid.map()的命名位置参数的数据。
3. 它必须能够接受color和label关键字参数,理想情况下它将非常有用。在大多数情况下,使用一个通用的**kwargs字典是最简单的,并将其传递给底层的绘图函数。
最简单的例子

def quantile_plot(x, **kwargs):
    qntls, xr = stats.probplot(x, fit=False)
    plt.scatter(xr, qntls, **kwargs)

g = sns.FacetGrid(tips, col="sex", size=4)
g.map(quantile_plot, "total_bill");


如果你想绘制一个双变量图,你应该编写函数接受先接受x轴变量,再接受y轴变量。

def qqplot(x, y, **kwargs):
    _, xr = stats.probplot(x, fit=False)
    _, yr = stats.probplot(y, fit=False)
    plt.scatter(xr, yr, **kwargs)

g = sns.FacetGrid(tips, col="smoker", size=4)
g.map(qqplot, "total_bill", "tip");


因为plt.scatter接受color和label参数并正确运行,我们可以轻松地再添加一个hue参数:

g = sns.FacetGrid(tips, hue="time", col="sex", size=4)
g.map(qqplot, "total_bill", "tip")
g.add_legend();

我们可以设定额外的美术元素用来区别hue,along with keyword arguments that won’t be depdendent on the faceting variables。

g = sns.FacetGrid(tips, hue="time", col="sex", size=4,
                  hue_kws={"marker": ["s", "D"]})
g.map(qqplot, "total_bill", "tip", s=40, edgecolor="w")
g.add_legend();

一些时候,将需要映射一个适合的color和label关键字参数以达到预期的效果。在这种情况下,您将会有明确地把握并熟悉处理自定义函数的逻辑。例如这种方法将允许使用映射plt.hexbin函数和那些类似的不方便使用FacetGrid API的调用:

def hexbin(x, y, color, **kwargs):
    cmap = sns.light_palette(color, as_cmap=True)
    plt.hexbin(x, y, gridsize=15, cmap=cmap, **kwargs)

with sns.axes_style("dark"):
    g = sns.FacetGrid(tips, hue="time", col="time", size=4)
g.map(hexbin, "total_bill", "tip", extent=[0, 50, 0, 10]);

绘制成对的关系

PairGrid允许你快速绘制拥有许多小子图的网格去可视化每一组数据间的关系。在PairGrid中每个行列都被分配给不同的变量,所以结果展示出数据集中成对的关系。这种风格的绘图有时被称为“散点图矩阵”,因为这是显示每个关系的最常见方式,但是PairGrid不仅限于散点图。
理解FacetGrid与PairGrid的区别很重要(。。我感觉很好理解,不翻译了)
PairGrid的基础用法与FacetGrid很为相似,首先初始化网格,然后通过.map传递绘图函数。pairplot()可以更加快速的绘图,当然牺牲了一些自由性。

iris = sns.load_dataset("iris")
g = sns.PairGrid(iris)
g.map(plt.scatter);


我们可以在对角线上传入不同的绘图函数,画出变量的概率分布图注意!概率分布图的横纵轴将不再与图中对应

g = sns.PairGrid(iris)
g.map_diag(plt.hist)
g.map_offdiag(plt.scatter);


给不同分类上不同的颜色是非常常用的方法

g = sns.PairGrid(iris, hue="species")
g.map_diag(plt.hist)
g.map_offdiag(plt.scatter)
g.add_legend();

默认情况下,每个数值型变量都将被画出,当然你可以只画出你想要的。

g = sns.PairGrid(iris, vars=["sepal_length", "sepal_width"], hue="species")
g.map(plt.scatter);


也可以对上三角和下三角区域使用不同的绘图函数,用来强调关系的不同方面(感觉只是炫酷了一点点~。~)

g = sns.PairGrid(iris)
g.map_upper(plt.scatter)
g.map_lower(sns.kdeplot, cmap="Blues_d")
g.map_diag(sns.kdeplot, lw=3, legend=False);


The square grid with identity relationships on the diagonal is actually just a special case, and you can plot with different variables in the rows and columns.

g = sns.PairGrid(tips, y_vars=["tip"], x_vars=["total_bill", "size"], size=4)
g.map(sns.regplot, color=".3")
g.set(ylim=(-1, 11), yticks=[0, 5, 10]);

美术风格当然是可配置的,你可以通过传入参数来自定义。

g = sns.PairGrid(tips, hue="size", palette="GnBu_d")
g.map(plt.scatter, s=50, edgecolor="white")
g.add_legend();


尽管PairGrid功能更加自由,但是pairplot()显然更加方便快捷。其默认散点图和条形图,将来还会加入跟多的图形(目前只可以在对角线区域画kde估计曲线,非对角线画回归曲线)

sns.pairplot(iris, hue="species", size=2.5);


您还可以使用关键字参数控制显示细节,并返回PairGrid实例进行进一步的调整

g = sns.pairplot(iris, hue="species", palette="Set2", diag_kind="kde", size=2.5)

你可能感兴趣的:(python,seaborn,数据可视化)