Python数据可视化-Seaborn(含组合图)

Seaborn是一个很好用的python数据可视化包。汇总一下之前做数据可视化时的一些注意事项和技巧。


Seaborn

为什么有的数据可视化给人感觉起来很好看很舒服,其实涉及到Seaborn的一些细节操作问题,这里收集了我所关注到的注意事项。

文章结构如下:

  1. Seaborn依赖的数据结构
  2. Matplotlib
  3. Heatplot
  4. Jointplot
  5. Violinplot
  6. 组合图(plt.plot+sns.heatplot)
    (1) 组合图的框架
    (2) 子图配置——heatplot
    (3) 子图配置——ax.plot
    (4) 其他

1. Seaborn依赖的数据结构

在使用Seaborn之前,需要强调和注意的是Seaborn依赖的数据结构。pandas的dataframe可以很方便地兼容Seaborn的数据输入。下面简单介绍从csv文件导入dataframe数据以及一些相关的处理:

import pandas as pd
dataframe = pd.read_csv(filedir, usecols=[colsname])  #  read data from csv file
dataframe.drop() 
dataframe.iloc[]

这里需要说明的是,对于dataframe数据,习惯上提前给列命名,方便之后Seaborn的使用,当然也可以在Seaborn中重新命名。

2. Matplotlib

Matplotlib可以很好的兼容Seaborn,可以通过Matplotlib对图片尺寸进行修改、ticklable及title等编辑、保存图片以及多个Seaborn子图的排列方式和尺寸进行编辑,同时,也可以实现Seaborn和Matplotlib共同作图。

(1) 图片尺寸

# 方法一
import matplotlib.pyplot as plt
f, ax = plt.subplots(figsize=(11, 9))
# 方法二
import pylab
pylab.rcParams['figure.figsize'] = (12.0,7.0) # 显示大小

(2) 图片标注及字体大小

import matplotlib.pyplot as plt
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.xlim([0,4000])
plt.legend(['line1,'line2','line3'],fontsize=17)
plt.xlabel('x',fontsize=17)
plt.ylabel('y',fontsize=17)
plt.title('title', fontsize=20)

(3) 保存图片

plt.savefig(filename+".png",format='png', bbox_inches='tight', transparent=True)

3. Heatplot

cmap = sns.diverging_palette(220, 10, as_cmap=True)
rc = {'font.size': 15, 'xtick.labelsize': 15, 'ytick.labelsize': 15}
sns.set(rc=rc)
# Draw the heatmap with the mask and correct aspect ratio
heatplt = sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
            square=True, linewidths=.5, cbar_kws={"shrink": .5}, annot=True, fmt=".2f")
Heatmap.png

其中,cmap可以定制heatmap的颜色,seaborn的heatmap当中的fmt参数可以修改显示数字的位数,例如".2f"表示float类型保留小数点后两位。

4. Jointplot

sns.jointplot(x=x, y=y, kind="hex",color='r')
Jointplot.png

5. Violinplot

vio = sns.violinplot(data=Error, orient="v",linewidth=0.6)
for i in range(4):
    plt.vlines(1.5+2*(i), -0.35, 0.35, colors = "c", linestyles = "dashed")

Violinplot

6. 组合图

很多时候在描述一个问题时需要对不同的图进行组合以达到表现的目的,例如将plt的曲线图和seaborn的heatplot组合起来,并且横轴相对应,标注要清楚可见。


组合图结构

这个时候需要根据以下步骤有条不紊地对图进行设置。

(1) 组合图的框架

首先确认你的图片当中包含几块,例如如果包含两块,那么分别的尺寸以及比例是怎样的。

fig = plt.figure(figsize=(xSize, ySize))
gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1])

比如,如上代码是做了一个两行一列的结构,并且纵向比例是3:1,整个图片的大小是(xSize, ySize)。

ax0 = plt.subplot(gs[0])
ax1 = plt.subplot(gs[1])

而subplot使用了gs为参数,确定了子图的句柄,可以通过对ax0或者ax1进行操作,以达到不同位置显示不同的图像的目的。

(2) 子图配置——heatplot

在子图当中,我们首先对heatplot进行操作,

heatplt = sns.heatmap(data, linewidths=0, ax=ax1, cmap="YlGnBu", annot=False,
                          yticklabels=['data'], xticklabels=xtick,
                          cbar=False)

注意点-1:

因为考虑到需要将heatplot的横轴与plt的曲线图横轴对齐,所以关闭图例显示,当然也可以将图例与横轴平行放置,但是为了美观,这里我关掉了cbar的显示。

注意点-2:

对于横轴较为密集的情况下,例如是一个很长的时间段,需要对横轴进行间隔标注显示,这样给人看起来很清楚,不会因为密密麻麻挤在一起导致看不清的问题。所以使用如下的配置:

import matplotlib.ticker as ticker
ax1.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))

tick_spacing是可以修改的参数,顾名思义,是标注间隔的意思,这里需要注意,tick_spacing需要和给定的标注序列统一,举个例子,比如现在需要给横轴标注1到100,共100个数字,但是由于太过密集,需要用到tick_spacing参数进行稀疏标注,那么在给heatplot的xticklabels传递参数时,就必须根据tick_spacing对序列进行系数处理,亲测如下代码无误:(仅限配置heatplot)

SliceStart = 0
SliceEnd = len(data)
tick_spacing = 10
xtick=range(SliceStart - tick_spacing, SliceEnd, tick_spacing)

需要注意的是必须减去tick_spacing,否则标注会错位。

(3) 子图配置——ax.plot

这里是曲线图部分,不做过多描述,有一点需要注意的就是,因为两个子图共用一个横坐标,所以第一行的图(也就是plot)的横坐标标注可以隐藏不显示,通过如下代码实现:

plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='both',  # both major and minor ticks are affected
        bottom=False,  # ticks along the bottom edge are off
        top=False,  # ticks along the top edge are off
        labelbottom=False)  # labels along the bottom edge are off

(4) 其他

为了确保两个图的横坐标对齐,每个子图配置结束后添加一行。

plt.xlim([0, LenData])

(5) 代码

from matplotlib import gridspec
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import pandas as pd
import numpy
from pandas import Series

def drawHeat_plot(line, data, xSize, ySize, xtick, tick_spacing, cols='sin',
                filename='HeatPlot', title='Demo',
                yticklabel=['Value']):  
    textFS = 80
    titleFS = 100
    LenData = len(line)
    rc = {'font.size': textFS, 'xtick.labelsize': textFS, 'ytick.labelsize': textFS, }
    sns.set(rc=rc)
    size = np.shape(data)
    fig = plt.figure(figsize=(xSize, ySize))
    gs = gridspec.GridSpec(2, 1, height_ratios=[2, 1])
    ax1 = plt.subplot(gs[1])

    heatplt = sns.heatmap(data, linewidths=0, ax=ax1, cmap="YlGnBu", annot=False,
                           xticklabels=xtick,
                          cbar=False, yticklabels=yticklabel)

    plt.xticks(fontsize=textFS)
    plt.yticks(fontsize=textFS)
    ax1.set_ylabel('Value', fontsize=textFS)
    ax1.set_xlabel('Time step', fontsize=textFS)
    plt.xlim([0, LenData])
    ax1.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
    
    
    ax0 = plt.subplot(gs[0])
    ax0.plot(line, linewidth=3)
    ax0.set_ylabel('Value', fontsize=textFS)
    plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='both',  # both major and minor ticks are affected
        bottom=False,  # ticks along the bottom edge are off
        top=False,  # ticks along the top edge are off
        labelbottom=False)  # labels along the bottom edge are off
    ax0.set_title(title, fontsize=titleFS)
    ax0.grid(linestyle='--', linewidth='0.5', color='black')
    plt.legend([cols + ' Data'], fontsize=textFS)
    plt.xlim([0, LenData])

    fig = heatplt.get_figure()
    fig.savefig(filename + ".png", format='png', bbox_inches='tight', transparent=True)

Demo数据及参数:

line = np.sin([3.14*i/20 for i in range(0,100)])
data = np.sin([3.14*i/20 for i in range(0,100)])
line = np.reshape(line,[100,])
data = np.reshape(data,[1,100])
xSize = 150
ySize = 30
SliceStart = 0
SliceEnd = 100
TickSpace = 10

运行代码:

drawHeat_plot(line, data, xSize, ySize, range(SliceStart - TickSpace, SliceEnd, TickSpace), tick_spacing=TickSpace, cols='sin',
                filename='HeatPlot', title='Demo')

运行结果:


Demo

总结:

数据可视化是一门学问,如何在一张有限的图上清楚有效地展示图片想要说明的信息。一方面,根据想要突出数据的哪方面的信息,选择合适类型的图型;另一方面,给读图的人一种清楚明了的感觉,需要对可视化图的细节——例如排布、字体、字体大小、图例、颜色等等各个方面进行调节。这样,做出figure才既能表达作图者想要表达的信息,也能让读图者清楚清爽地领会数据呈现出来的信息。
之后笔者接触到其他类型的可视化以及相关注意事项时会继续在这篇文章中书写。如有意见和建议请各位提出~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容