Python

[可视化]探索性数据2 双变量

2020-01-27  本文已影响0人  DDuncan
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sb

一、双变量

提纲

数据类型
数值变量 vs 数值变量 散点图scatterplots
plt.scatter()
sb.regplot()
数值变量 vs 分类变量 小提琴图violin plot
sb.violinplot()
箱线图box plot
sb.boxplot()
分类变量 vs 分类变量 分组条形图clustered bar charts(基于单变量条形图)
sb.countplot(, hue=)
二维直方图/条形图 热图heat maps
plt.hist2d()
技巧
分面:降维描述 sb.FacetGrid()
调整后的条形图bar charts 使用第二个变量的平均值而非数据统计
sb.barplot(, x= , y=, ci= )
sb.pointplot(, x=, y=)
调整后的直方图 plt.hist(, x=, weights=)
折线图line plots plt.errorbar()
补充图形
Q-Q 图 当数据分布不符合正态分布时
蜂群图Swarm Plots sb.swarmplot()
轴须图Rug Plot sb.rugplot()
带状图Strip Plot sb.stripplot()
叠嶂图Ridgeline Plot g = sb.FacetGrid()
g.map()
堆积图 前提:总量保持一致(比如100%)

1.1 散点图(数值 vs 数值)

plt.scatter(data = df, x = 'num_var1', y = 'num_var2')

plt.scatter(x, y, s=None, c=None, marker=None, 
cmap=None, norm=None, vmin=None, vmax=None, alpha=None, 
linewidths=None, verts=None, edgecolors=None, hold=None, 
data=None, **kwargs)
#参数c:颜色,可以设置颜色列表  'blue' 'red'
#参数s:图片缩放比例
#参数**kwargs
#参数label="Luck"  幸运三叶草
sb.regplot(data = df, x = 'num_var1', y = 'num_var2')
#线性相关性:皮尔逊相关系数r
#参数reg_fit 回归拟合

sb.regplot(x, y, data=None, x_estimator=None, x_bins=None, 
x_ci='ci', scatter=True, fit_reg=True, ci=95, n_boot=1000, units=None, 
order=1, logistic=False, lowess=False, robust=False, logx=False, 
x_partial=None, y_partial=None, truncate=False, dropna=True, 
x_jitter=None, y_jitter=None, label=None, color=None, marker='o', 
scatter_kws=None, line_kws=None, ax=None)
#seaborn的散点图高端了一点,包含了可以绘制拟合线和置信区间等额外功能
#参数color:设置颜色
#参数fit_reg:是否绘制拟合线和执行区间,注意并非课程中的reg_fit哦
#参数scatter:是否显示散点
#参数ci:执行区间大小 [0, 100] 
可以创建具有回归拟合的散点图,默认的回归函数是线性回归,并且包含回归估计置信区间(阴影部分) sb.regplot()
  • 问题:数据重叠overplotting
    1). 透明度
    plt.scatter(alpha= )
    sb.regplot(scatter_kws = {'alpha' : 1/3})
    2). 抖动
    sb.regplot(x_jitter = 0.2, y_jitter = 0.2)
    每个点在真实值的 ±0.2 范围内抖动
    3). 随机减少采样点

1.2 热图(直方图: 数值 vs 数值; 条形图: 分类 vs 数值)

直方图的二维版本,可以替代散点图
和散点图一样,要绘制的两个数值变量位于两个坐标轴上
和直方图类似,图表区域被划分为网格,累计每个网格的数据点数量
因为没有空间表示条形的高度,因此用网格颜色表示计数

plt.hist2d(data, x, y, bins, cmap, cmin)
#参数cmin 单元格要绘制出来的数据的下限值(关注核心数据)
#单元格添加注释 plt.text(x轴位置,y轴位置,数值, ha, va, color)

plt.hist2d(data = df, x = '', y ='', bins=[bins_x, bins_y], cmap, cmin)
plt..hist2d(x, y, bins=10, range=None, normed=False, weights=None, cmin=None, cmax=None, hold=None, data=None, **kwargs)
#返回一个2d数组h2d[0](热图颜色值),和两个1d的分组边界值h2d[1]、h2d[2],plt.QuadMesh h2d[3]
    #h2d[0].shape[0] x轴==行方向
    #h2d[0].shape[1] y轴==列方向
    #h2d[0][i][j]表示二维图(i, j)位置的数值(颜色值)

#参数x,y, bins(设置方式也跟hist一致,只是是二维,因为要设置x和y的bins)
#参数cmin:设置多少count以下记为空,那么就不会被填充颜色
#参数cmax:就是大于多少就会被记为空,不填充颜色

plt.colorbar(mappable=None, cax=None, ax=None, **kw)
#只对当前图表生效,所以要想多个生效就得每个图表下跟一个

如果散点太离散,或者数据点的数据量太密集,透明度已经不足以使用的情况下,可以用热图:


热图:优秀示例
sb.heatmap(data_adjusted, annot = True, fmt = 'd')
#参数annot = True 可以在每个单元格中显示注释
#参数fmt = 'd' 表示注释将变成整数形式;为了避免有些类别没有数量,要显示出 NaN 值,你可以设置 fmt = '.0f'

seaborn.heatmap(data, vmin=None, vmax=None, cmap=None, 
center=None, robust=False, annot=None, fmt='.2g', annot_kws=None, 
linewidths=0, linecolor='white', cbar=True, cbar_kws=None, 
cbar_ax=None, square=False, xticklabels='auto', yticklabels='auto', 
mask=None, ax=None, **kwargs)
#参数annot = True 显示统计标号
#参数fmt 标号格式,比如"d"就是整数的形式
#参数data:dataframe
#参数vmin, vmax:界限,决定不被标注颜色的部分
#参数cmap:老样子,选颜色映射表
#参数centor:改变颜色映射的趋势
#参数linewidths linecolor :格子的分割线的颜色和宽度
  • 准备工作
    .groupby()
    .reset_index(name='count') count为数据表中新的一列,便于.pivot()
    .pivot(index='VClass', columns='trans_type', values='count' ) heatmap 数据整理成二维表格

2.1 小提琴图(分类 vs 数值)

sb.violinplot(data = df, x = 'cat_var', y = 'num_var', color= , inner= )
#参数inner = 'quartile’绘制三条虚线分别表示三个四分位数 Q1-Q3 Q2表示中位数

sb.violinplot(x=None, y=None, hue=None, data=None, order=None, 
hue_order=None, bw='scott', cut=2, scale='area', scale_hue=True, 
gridsize=100, width=0.8, inner='box', split=False, dodge=True, 
orient=None, linewidth=None, color=None, palette=None, 
saturation=0.75, ax=None, **kwargs)
#参数:x y hue是选定的数据列,x一般是定性变量,y一般是定量变量,hue一般是另外一个分割x的定性变量
#参数split:如果设定为True,hue对比的那两个小提琴图就会合并成一个小提琴图,好做对比
#参数inner:有以下几种选择 {“box”, “quartile”, “point”, “stick”, None}
散点图与小提琴图

2.2 箱线图(分类 vs 数值)

箱线图是比小提琴图更清晰的数据汇总。使用箱线图更容易比较不同组的统计值
另一方面,箱线图对数据分布的细节描绘没有小提琴图清晰:无法在 Alpha 级别的值中看到微弱的双峰性。
小提琴图可能更适合探索数据,尤其因为 seaborn 还默认地在小提琴图中包含了箱线图

sb.boxplot(data = df, x = 'cat_var', y = 'num_var', color= , inner=)

sb.boxplot(x=None, y=None, hue=None, 
data=None, order=None, hue_order=None, 
orient=None, color=None, palette=None, 
saturation=0.75, width=0.8, dodge=True, 
fliersize=5, linewidth=None, whis=1.5, 
notch=False, ax=None, **kwargs)
#参数x y hue是选定的数据列,x一般是定性变量,y一般是定量变量,hue一般是另外一个分割x的定性变量,比如,什么学历x大概赚多少钱y,那么想观察什么学历下,性别分类大概赚多少钱,Hue就是性别(有点groupby的意思)
#参数data:老样子是dataframe
#参数color:是设置所有图案的颜色
#参数palette:是seaborn.color_palette得来的
#参数linewidth:线的宽度
#参数orient:也可以直接调整绘图方向。"h"和“v”
#参数dodge:默认是True,设置为False的话,hue的图形就不会调整顺序和宽度跑到对比格子旁边去了。
#参数order, hue_order 是决定输出顺序,一般是以一个列表作为排序

3 分组条形图(簇状条形图) (分类 vs 分类)

基于单变量条形图

ax = sb.countplot(data = df, x = 'cat_var1', hue = 'cat_var2')
#横轴是x
#第二变量是分类/分组hue
#纵轴是统计量:比如频数
ax.legend(loc = 8, ncol = 3, framealpha = 1, title = 'cat_var2')

seaborn.countplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient=None, color=None, palette=None, saturation=0.75, dodge=True, ax=None, **kwargs)
分组条形图
热图和分组条形图

4 序列-折线图

plt.errorbar(data = df, x = 'num_var1', y = 'num_var2')
#参数误差线yerr 设置为标准差
#参数c 线的颜色
#参数linestyle 线的格式

plt.errorbar(x, y, yerr=None, xerr=None, fmt='', ecolor=None, elinewidth=None, capsize=None, barsabove=False, lolims=False, uplims=False, xlolims=False, xuplims=False, errorevery=1, capthick=None, hold=None, data=None, **kwargs)
#参数x, y定义数据位置
#参数xerr, yerr定义了errorbar的size大小

每个唯一 x 值或 x 值的分组区间仅绘制一个点
如果一个 x 分组区间中有多个观测值,那么该点在折线图中绘制的 y 值将为该数据点在分组中的概括统计值(例如均值或中位数)
如果 x 变量表示时间,则数据的折线图通常称之为时间序列图表
通常,在每个时间段内,我们只有一个观测值,例如股票图表或货币汇率图表

  • 问题
    plt.errorbar(data = df, x = 'num_var1', y = 'num_var2')
    原始折线图:无序
  • 解决方法:数据有序化
    1). 设置分组边界和中心点:有序序列
    xbin_edges = np.arange(0.5, df['num_var1'].max()+0.25, 0.25)
    xbin_centers = (xbin_edges + 0.25/2)[:-1]
    2). pd.cut():将原始数据归类到有序序列
    data_xbins = pd.cut(df['num_var1'], xbin_edges, right = False, include_lowest = True)
    3). pd.groupby():汇总统计值,作为y轴数据
    y_means = df['num_var2'].groupby(data_xbins).mean()
    y_sems = df['num_var2'].groupby(data_xbins).sem()
    4). 绘制图表
    plt.errorbar(x = xbin_centers, y = y_means, yerr = y_sems) 参数误差线 yerr 设置为标准差
    折线图
df_window = df.sort_values('num_var1').rolling(n)
x_winmean = df_window.mean()['num_var1']
y_median = df_window.median()['num_var2']
y_q1 = df_window.quantile(.25)['num_var2']
y_q3 = df_window.quantile(.75)['num_var2']
plt.scatter(data=df, x='num_var1', y='num_var2')
plt.errorbar(x=x_winmean, y=y_median, c=line_color)
plt.errorbar(x=x_winmean, y=y_q1, c=line_color, linestyle='--')
plt.errorbar(x=x_winmean, y=y_q3, c=line_color, linestyle='--')
plt.savefig('Lineplot3.png')
折线图:移动平均
g = sb.FacetGrid(data=df, hue='', size=)
g.map(plt.hist, '', bins=, histtype='step')
g.add_legend()
多变量折线图

遗憾的是,“Alpha” 曲线是被其他三条曲线覆盖了,因为计数相对较低,导致出现很多重叠的地方

5.1 调整后的条形图(分类+统计量)

调整后的长条高度不再代表每个值的数量,而用来表示第二个变量的均值或其他统计量

sb.barplot(data = df, x = 'cat_var', y = 'num_var', color = base_color)
#参数errwidth  默认包含误差线:表示基于方差和样本大小的均值不确定性
#参数 ci = 'sd' 统计数据点的标准差,而非均值
sb.pointplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, estimator=<function mean>, ci=95, n_boot=1000, units=None, markers='o', linestyles='-', dodge=False, join=True, scale=1, orient=None, color=None, palette=None, errwidth=None, capsize=None, ax=None, **kwargs)
#使用散点图显示点估计和置信区间,跟上面相比是将平均值绘制为点,而不是长条。
#seaborn.pointplot擅长总结定量变量和定性变量之间的关系。

#参数join:如果设为True,就会画那个点和点之间的估计线,设为False就不画
#参数linestyles:设置线的格式,可以设置为虚线等等"- -",当然设置为" "空格的话就是没有线
调整后的条形图
sb.pointplot(data = df, x = 'cat_var', y = 'num_var', linestyles = "")
#参数 linestyles = "" 删除折线 默认情况下,pointplot 将用折线连接值
将平均值绘制为点,而不是长条 调整后的点图

如果数值变量本身是二元变量,值仅包括 0 和 1,那么箱线图或小提琴图将无法呈现足够的信息,而调整后的条形图最适合显示这些数据


针对二值分类变量

5.2 调整后的直方图(数值+统计量)

plt.hist(data=df, x='num_var', bins=bin_edges, weights=num_var_wts)
#参数weights  使长条高度表示除数据点数量以外的其他值
调整后的直方图

结果:每一个x轴分组的面积(权重*组内的数据数量)==y变量在该组内的“平均结果”

6.1 补充 Q-Q 图

当数据分布不符合正态分布时

预期值:norm.ppf()
对于标准正态分布(mean = 0, standard deviation = 1)来说,ppf(0.25) = -0.674 ppf(0.5)=0 ppf(0.75)=0.674

n_points = 120
bin_size=0.5

plt.subplot(1,2,1)
unif_data = np.random.uniform(, n_points)
plt.hist(x=unif_data, bins=)

samp_mean = unif_data.mean()
samp_std = unif_data.std()

x=np.linspace()
y=norm.pdf(x, samp_mean, samp_std)
plot(x, y)

plt.subplot(1,2,2)
qq_data = (np.arange(n_points) - 0.5) / n_points
expected_scores = norm.pdf(qq_data)
data_scores = (np.sort(unif_data)  - samp_mean) /sam_std
plt.scatter(expected_scores, data_scores)

plt.axis('equal')
plt.xlabel('Expected Standard Scores')
plt.ylabel('Observed Standard Scores')
Q-Q图

看到一条 S 形曲线。曲线中间部分值的趋势近似为线性,但斜率比期望的 y = x 更陡。同时在边缘上,斜率非常缓,因为均匀分布固定在有限范围内,但正态分布值的尾部预期会更远

可以在左侧图中的叠加分布线中看到这一点,即使在数据的边缘,理论上的正态曲线仍然有相当高的高度。所有这些都导致随机生成的均匀分布数据不能与正态分布近似贴合

6.2 蜂群图Swarm Plots

和散点图类似,每个数据点根据在两个变量上的值确定在图表中的位置。点放置在尽量接近真实值的位置,不允许有任何重叠现象,不是像在正常散点图中那样随机抖动数据点

sb.swarmplot(data=df, x='cat_var', y='num_var', color=)

seaborn.swarmplot(x=None, y=None, hue=None, 
data=None, order=None, hue_order=None, 
dodge=False, orient=None, color=None, 
palette=None, size=5, edgecolor='gray', linewidth=0, ax=None, **kwargs)
蜂群图

虽然由于位置抖动而出现一些变形,但是我们也可以确切地了解每个点实际位于何处,消除了小提琴图中可能出现的长尾。
但是,只有数据量很少或适中时,才适合使用蜂群图。如果有太多的数据点,那么不能重叠的限制将导致变形严重,或者需要很多空间才能很好地绘制数据
此外,数据点太多实际上会分散注意力,使我们更难发现图表中的关键规律

6.3 轴须图Rug Plot

边缘分布是变量的单变量分布,忽略任何其他变量的值

g = sb.JointGrid(data=df, x='num_var1', y='num_var2')
g.plot_joint(plt.scatter)
g.plot_marginals(sb.rugplot, height = 0.25)
#参数height  指定轴须图的刻度为边缘轴大小高度(相邻刻度的距离)的 0.25 倍
轴须图

此例中,轴须图很合适,因为数据并不多或过于密集。在其他情形下,直方图或密度曲线可能更合适

6.4 带状图Strip Plot

本质:分类散点图

sb.stripplot(data=df, x='num_var', y='cat_var', color=base_color)

注意右边小提琴图中的竖线:越黑表示越密集


带状图

6.5 叠嶂图Ridgeline Plot

近年来最热门的新型可视化类型之一

一系列垂直分面的折线图或密度曲线图,只是 y 轴有一定的重叠 叠嶂图
group_means = df.groupby(['many_cat_var']).mean()
group_order = froup_means.sort_values(['num_var'], ascending=False).index

g = sb.FacetGrid(data=df, col='many_cat_var', col_wrap=5, size=2, col_order=group_order)
g.map(plt.hist, 'num_var', bins=np.arange(5, 15+1, 1))
g.set_titles('{col_name}')
#索引排序:按照均值下降趋势(上述直方图的顺序有问题:R10均值最大)

sb.FacetGrid(data, row=None, 
col=None, hue=None, col_wrap=None, 
sharex=True, sharey=True, size=3, aspect=1, 
palette=None, row_order=None, col_order=None, 
hue_order=None, hue_kws=None, dropna=True, 
legend_out=True, despine=True, 
margin_titles=False, xlim=None, ylim=None, subplot_kws=None, gridspec_kws=None)
#参数data:往常一样,dataframe
#参数row, col, hue : 不是会建立几个小图表吗,row就是行拆分是拆分了什么分类,col就是列拆分拆分了什么,hue就是一个表内部的分类(常用不同颜色区分不同分类)
#参数col_wrap:在每行的分类下,来决定一列放几个
#参数size,aspect,又看到这两了,还是同样,每个子图表高度和宽高比,
#参数col,row,hue_order 决定了图表输出中列,行,hue的顺序,所以一般是列表形式
原始数据(分面直方图)
  • 待处理

1). 将分布图的形式从直方图改为核密度估计,使叠嶂图中的每个“山峰”更平滑
2). 需要按行划分级别,以便这些“山峰”堆叠在一起

group_means = df.groupby(['many_cat_var']).mean()
group_order = froup_means.sort_values(['num_var'], ascending=False).index

g = sb.FacetGrid(data=df, row='many_cat_var', size=0.5, aspect=12, row_order=group_order, gridspec_kws={'hspace': -0.2})
g.map(sb.kdeplot, 'num_var', shade=True)
g.set(yticks=[])
g.despine(left=True)

#set the transparency of each subplot to full
g.map(lambda **kwargs: plt.gca().patch.set_alpha(0))

#remove subplot titles and write in new labels
def label_text(x, **kwargs):
    plt.text(4, 0.02, x.iloc[0], ha='center', va='bottom')
g.map(label_text, 'many_cat_var')
g.set_xlabels('num_var')
g.set_titles('')
#参数gridspec_kws:通过 Matplotlib 的 GridSpec 类调整网格中子图的排列
#将 "hspec" 参数设置为负值,可以使子图的轴边界垂直重叠
#通过g.set()移除刻度
#通过g.despine()来移除 y 轴
#利用了 FacetGrid 对象的 map函数来完成图表修改
    #使用map应用透明度:设置了一个匿名 lambda 函数,该函数获取当前的 Axes 对象 (gca) , 选择其背景 (patch),将该背景的透明度设置满(set_alpha(0))
    #map 的第二个参数,它将一个 pandas Series 发送到第一个参数指定的函数。这个 Series 是筛选出来的仅包含第二个 map 参数指定的列,只有适用于每个分面的行
    #map 也会自动向指定的函数发送一些像 ‘color’ 这样的通用关键字参数。因此尽管这里我并没有指定这样的参数,仍然需要 **kwargs 来捕获关键字参数
    #me-理解 g.map(plot, 'column') 第二个参数是第一个参数的的对象

6.6 堆积图

前提:总量保持一致(比如100%)
错误示例:总量不一致


堆积图:错误示例

7 补充

7.1 sb.factorplot()

sb.factorplot(x=None, y=None, hue=None, 
data=None, row=None, col=None, 
col_wrap=None, estimator=<function mean>, 
ci=95, n_boot=1000, units=None, order=None, 
hue_order=None, row_order=None, 
col_order=None, kind='point', size=4, aspect=1, 
orient=None, color=None, palette=None, 
legend=True, legend_out=True, sharex=True, 
sharey=True, margin_titles=False, 
facet_kws=None, **kwargs)
#它是seaborn下的一个方法,有点类似FacetGrid,它合并了FacetGrid和定性-定量的图表(柱状,小提琴,箱线等),使用上,比FacetGrid方便点

7.2 sb.lmplot()

sb.lmplot(x, y, data, hue=None, col=None, 
row=None, palette=None, col_wrap=None, size=5, 
aspect=1, markers='o', sharex=True, sharey=True, 
hue_order=None, col_order=None, 
row_order=None, legend=True, legend_out=True,
 x_estimator=None, x_bins=None, x_ci='ci', 
scatter=True, fit_reg=True, ci=95, n_boot=1000, 
units=None, order=1, logistic=False, 
lowess=False, robust=False, logx=False, 
x_partial=None, y_partial=None, truncate=False, 
x_jitter=None, y_jitter=None, scatter_kws=None, 
line_kws=None)
#跟上面的factorplot很相似,不过组合的是FacetGrid和 seaborn.regplot散点图(定量-定量)

7.3 折线图 sb.tsplot()

sb.tsplot(data, time=None, unit=None, 
condition=None, value=None, err_style='ci_band', 
ci=68, interpolate=True, color=None, estimator=
<function mean>, n_boot=5000, err_palette=None, 
err_kws=None, legend=True, ax=None, **kwargs)
#参数err_style: {ci_band, ci_bars, boot_traces, boot_kde, unit_traces, unit_points}
#参数err的图样,默认就是一个曲线,常用还有ci_bars表示误差线
#参数ci: float or list of floats in [0, 100] or “sd” or None跟上面的误差线很像,要么表示置信区间,要么表示标准差,None就是没有误差线
#参数interpolate :True或者False,表示两点间是否画上插值的线
#参数condition :大概就是说会根据不同条件来绘制不同的折线
上一篇下一篇

猜你喜欢

热点阅读