Python可视化——Matplotlib & Seaborn

本文展示Python中最基本的可视化工具MatplotlibSeaborn的用法

1.导入库和常规设置

import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline

from datetime import datetime
import os

os.chdir(r'file_path')
plt.rcParams['font.sans-serif'] = ['SimHei']  # 中文字体设置-黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
sns.set(font='SimHei')  # 解决Seaborn中文显示问题
# 设置一下常用颜色
r_hex = '#dc2624'     # red,       RGB = 220,38,36
dt_hex = '#2b4750'    # dark teal, RGB = 43,71,80
tl_hex = '#45a0a2'    # teal,      RGB = 69,160,162
r1_hex = '#e87a59'    # red,       RGB = 232,122,89
tl1_hex = '#7dcaa9'   # teal,      RGB = 125,202,169
g_hex = '#649E7D'     # green,     RGB = 100,158,125
o_hex = '#dc8018'     # orange,    RGB = 220,128,24
tn_hex = '#C89F91'    # tan,       RGB = 200,159,145
g50_hex = '#6c6d6c'   # grey-50,   RGB = 108,109,108
bg_hex = '#4f6268'    # blue grey, RGB = 79,98,104
g25_hex = '#c7cccf'   # grey-25,   RGB = 199,204,207


2.基础元素概览

2.1四大容器

Python可视化——Matplotlib & Seaborn


四大容器:
Figure → Axes → Axis → Ticks
图 → 坐标系 → 坐标轴 → 刻度

  • 在坐标轴和刻度上添加标签

  • 在坐标系中添加线、点、网格、图例和文字

  • 在图中添加图例


要画出一幅有内容的图,需要在容器里添加基础元素比如线 (line), 点(marker), 文字 (text), 图例 (legend), 网格 (grid), 标题 (title), 图片 (image) 等,具体来说

画一条线,用 plt.plot() 或 ax.plot()

画个记号,用 plt.scatter() 或 ax.scatter()

添加文字,用 plt.text() 或 ax.text()

添加图例,用 plt.legend() 或 ax.legend()

添加图片,用 plt.imshow() 或 ax.imshow()

    from PIL import Image
    plt.figure()
    plt.xticks([]), plt.yticks([])
    im = np.array(Image.open('you_picture_path'))
    plt.imshow(im)
    plt.show()


Python可视化——Matplotlib & Seaborn

2.2 两种推荐画法

两种生成坐标系的推荐代码

第一种:同时生成图和坐标系

fig, ax = plt.subplots()

第二种:先生成图,再添加坐标系

fig = plt.figure()

ax = fig.add_subplot(1,1,1)


3.Matplotlib画图实操

3.1导入数据
data1 = pd.read_csv( 'S&P500.csv', 
                    index_col=0, 
                    parse_dates=True,
                    dayfirst=True )
data1.head(3).append(data1.tail(3))
Open High Low Close Adj Close Volume
Date
1950-01-03 16.660000 16.660000 16.660000 16.660000 16.660000 1260000
1950-01-04 16.850000 16.850000 16.850000 16.850000 16.850000 1890000
1950-01-05 16.930000 16.930000 16.930000 16.930000 16.930000 2550000
2019-04-22 2898.780029 2909.510010 2896.350098 2907.969971 2907.969971 2997950000
2019-04-23 2909.989990 2936.310059 2908.530029 2933.679932 2933.679932 3635030000
2019-04-24 2934.000000 2936.830078 2926.050049 2927.250000 2927.250000 3448960000
spx = data1[['Adj Close']].loc['2007-01-01':'2010-01-01']
spx.head(3).append(spx.tail(3))
Adj Close
Date
2007-01-03 1416.599976
2007-01-04 1418.339966
2007-01-05 1409.709961
2009-12-29 1126.199951
2009-12-30 1126.420044
2009-12-31 1115.099976
data2 = pd.read_csv( 'VIX.csv', index_col=0, 
                               parse_dates=True,
                               dayfirst=True )
vix = data2[['Adj Close']].loc['2007-01-01':'2010-01-01']
vix.head(3).append(vix.tail(3))
Adj Close
Date
2007-01-03 12.040000
2007-01-04 11.510000
2007-01-05 12.140000
2009-12-29 20.010000
2009-12-30 19.959999
2009-12-31 21.680000

用 plt.rcParams 可查看上图的所有默认属性 (非常多的属性值)

3.2 先画图再添加坐标系的方式

# 图的大小和像素 (w*dpi, h*dpi)即(1600, 600)
fig = plt.figure( figsize=(16,6), dpi=100 )  

# 在图中 (fig) 添加了一个坐标系 (ax),然后所有操作都在 ax 里面完成
ax1 = fig.add_subplot(1, 1, 1)

x = spx.index
y1 = spx.values
y2 = vix.values

# 画图,并设置颜色,宽度 (2 像素) 和风格 (连续线)
ax1.plot(y1, color=dt_hex, linewidth=2, linestyle='-', label='S&P500')

# 设置横轴和纵轴的边界
ax1.set_xlim(-1, len(x)+1)
ax1.set_ylim(np.vstack([y1, y2]).min()*0.8, np.vstack([y1, y2]).max()*1.2)


# 先用 ax.set_ticks() 设置出数值刻度
# 再用 ax.set_xticklabels() 在对应的数值刻度上写标签
x_tick= range(0, len(x), 40)
x_label = [x[i].strftime('%Y-%m-%d') for i in x_tick]
ax1.set_xticks(x_tick)
ax1.set_xticklabels(x_label, rotation=90)

# 添加图例 (legend), loc = 0 表示 matplotlib 自动安排一个最好位置显示图例,而 frameon = True 给图例加了外框 
ax1.legend(loc='upper left', frameon=True)  

# Add a second axes
ax2 = ax1.twinx()

ax2.plot(y2, color=r_hex, linewidth=2, linestyle='-', label='VIX')
ax2.legend(loc='upper right', frameon=True)


plt.show()

Python可视化——Matplotlib & Seaborn

添加第二幅图也很简单,用两次 plt.plot() 或者 ax.plot() 即可。

这里面用的是 plt 没用 ax,没有特殊原因,在本例中两者可以随意使用,

但两者在使用「.methods」时有个小细节:

plt.xlim

plt.ylim

plt.xticks


ax.set_xlim

ax.set_ylim

ax_set_xticks

3.3 同时生成图和坐标系的画法

# plt版本

plt.figure( figsize=(16,6), dpi=100 )

# subplot 1
plt.subplot(2, 1, 1)

x = spx.index
y1 = spx.values


plt.plot(y1, color=dt_hex, linewidth=2, linestyle='-', label='S&P500')
plt.xlim(-1, len(x)+1)
plt.ylim(y1.min()*0.8, y1.max()*1.2)

x_tick= range(0, len(x), 40)
x_label = [x[i].strftime('%Y-%m-%d') for i in x_tick]

plt.xticks(x_tick, x_label, rotation=90)
plt.legend(loc='upper left', frameon=True)

# subplot 2
plt.subplot(2, 1, 2)
y2 = vix.values

plt.plot(y2, color=r_hex, linewidth=2, linestyle='-', label='VIX')
plt.xlim(-1, len(x)+1)
plt.ylim(y2.min()*0.8, y2.max()*1.2)

plt.xticks(x_tick, x_label, rotation=45)
plt.legend(loc='upper left', frameon=True)

plt.show()

Python可视化——Matplotlib & Seaborn

3.4 设置标注

# 设置标注版本

fig = plt.figure( figsize=(16,6), dpi=100 )

# 定义危机事件,以元组的列表存储
crisis_data = [(datetime(2007, 10, 11), 'Peak of bull market'),
               (datetime(2008, 3, 12), 'Bear Stearns Fails'),
               (datetime(2008, 9, 15), 'Lehman Bankruptcy'),
               (datetime(2009, 1, 20), 'RBS Sell-off'),
               (datetime(2009, 4, 2), 'G20 Summit')]


ax1 = fig.add_subplot(1, 1, 1)

x = spx.index
y1 = spx.values
y2 = vix.values


ax1.plot(y1, color=dt_hex, linewidth=2, linestyle='-', label='S&P500')
ax1.set_xlim(-1, len(x)+1)
ax1.set_ylim(np.vstack([y1, y2]).min()*0.8, np.vstack([y1, y2]).max()*1.2)


x_tick= range(0, len(x), 40)
x_label = [x[i].strftime('%Y-%m-%d') for i in x_tick]
ax1.set_xticks(x_tick)
ax1.set_xticklabels(x_label, rotation=90)
ax1.legend(loc='upper left', frameon=True)

init_tick = list(range(0, len(x), 40))

# 定义容器,常规日期标签 init_tick,五个事件日期标签 impt_tick
impt_tick = []
impt_date = []

# 用 for 循环读取 crisis_data 里面每个日期 date 和事件 label
for date, label in crisis_data:
    date = date.strftime('%Y-%m-%d')
    impt_date.append(date)
    
    # 获取每一个 date 在整个日期数组中的索引 xi,以及对应的 spx 值 yi
    xi = x.get_loc(date)
    impt_tick.append(xi)
    yi = spx.asof(date)
    
    # 用 scatter() 函数画出一个圆点,标注事件在 spx 折现上的位置
    ax1.scatter(xi, yi, 80, color=r_hex)
    
    # 事件标注,在 annotate() 函数里设置了事件,箭头坐标,事件打印的坐标,箭头性质,以及对齐属性
    ax1.annotate(label, xy=(xi, yi + 60),
                xytext=(xi, yi + 300),
                arrowprops=dict(facecolor='black', headwidth=4, width=1, headlength=6),
                horizontalalignment='left', verticalalignment='top'
                )

x_tick = init_tick + impt_tick
x_label = [x[i].strftime('%Y-%m-%d') for i in x_tick]
ax1.set_xticks(x_tick)
ax1.set_xticklabels(x_label, rotation=90)

for i, label in enumerate(ax1.get_xticklabels()):
    if i >= len(init_tick):
        label.set_color(r_hex)
        label.set_fontweight('bold')
    else:
        label.set_fontsize(9)

# Add a second axes
ax2 = ax1.twinx()

ax2.plot(y2, color=r_hex, linewidth=2, linestyle='-', label='VIX', alpha=0.3)  # 透明度
ax2.legend(loc='upper right', frameon=True)


plt.show()

Python可视化——Matplotlib & Seaborn

4.图表的选择与画法

在做图表设计时候经常面临着怎么选用合适的图表,图表展示的关系分为四大类:

  • 分布 (distribution)

  • 联系 (relationship)

  • 比较 (comparison)

  • 构成 (composition)


Python可视化——Matplotlib & Seaborn

直方图 (histogram chart),又称质量分布图,是一种统计报告图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据类型,纵轴表示分布情况。在 Matplotlib 里的语法是

  • plt.hist()

  • ax.hist()


散点图 (scatter chart) 用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种联系的分布模式。在 Matplotlib 里的语法是

  • plt.scatter()

  • ax.scatter()


折线图 (line chart) 显示随时间而变化的连续数据,因此非常适用于显示在相等时间间隔下数据的趋势。在 Matplotlib 里的语法是:

  • plt.plot()

  • ax.plot()


饼状图 (pie chart) 是一个划分为几个扇形的圆形统计图表,用于描述量、频率或百分比之间的相对关系。 在饼状图中,每个扇区面积大小为其所表示的数量的比例。在 Matplotlib 里的语法是:

  • plt.pie()

  • ax.pie()

# 查看所有的色彩风格
print(plt.style.available)
['bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark-palette', 'seaborn-dark', 'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'seaborn', 'Solarize_Light2', 'tableau-colorblind10', '_classic_test']

seaborn-colorblind 和 tableau-colorblind10 是专门为色盲考虑的色彩风格

可以设置:
plt.style.use('ggplot')

plt.style.use('seaborn-colorblind')

plt.style.use('tableau-colorblind10')


5.Seaborn画图

iris_data = pd.read_csv('iris.csv')
iris_data.head(3).append(iris_data.tail(3))
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
147 6.5 3.0 5.2 2.0 virginica
148 6.2 3.4 5.4 2.3 virginica
149 5.9 3.0 5.1 1.8 virginica

用 set_style() 选五种风格:darkgrid, whitegrid, dark, white 和 ticks .

用 set_palette() 六种调色盘:deep, muted, pastel, bright, dark 和 colorblind

sns.set_style('darkgrid')  # 将风格设置为 darkgrid (背景变成带网格的灰色)
sns.set_palette('colorblind')  # 色板设置成 colorblind 为色盲用户着想
sns.pairplot( iris_data, hue='species',markers=['o','s','D'] )  # 将不同类用圆形 (o)、正方形 (s) 和方块 (D) 来标记
<seaborn.axisgrid.PairGrid at 0x1ff91688198>

Python可视化——Matplotlib & Seaborn

# 选择子集图
sns.set_style('whitegrid')
# sns.pairplot( iris_data, 
#               vars=['sepal_width', 
#                     'sepal_length'] )

sns.pairplot( iris_data, 
              x_vars=['sepal_width', 
                      'sepal_length'],
              y_vars=['petal_width', 
                      'petal_length'])
<seaborn.axisgrid.PairGrid at 0x1ff93aca198>

Python可视化——Matplotlib & Seaborn

# 线性回归图,设置参数 kind = 'reg'
sns.set_style('ticks')
sns.set_palette('dark')
sns.pairplot( iris_data, kind='reg' )
<seaborn.axisgrid.PairGrid at 0x1ff940eb748>

Python可视化——Matplotlib & Seaborn

# 核密度图(对角线),设置里面参数 diag_kind = 'kde'
sns.set_palette('bright')
sns.pairplot( iris_data, diag_kind='kde' )
<seaborn.axisgrid.PairGrid at 0x1ff946b9f98>

Python可视化——Matplotlib & Seaborn

条形图 (barplot)

计数图 (countplot)

点图 (pointplot)

箱形图 (boxplot)

小提琴图 (violinplot)

titanic = sns.load_dataset(".seaborn-data-master/titanic")
titanic.head(3).append(titanic.tail(3))
survived pclass sex age sibsp parch fare embarked class who adult_male deck embark_town alive alone
0 0 3 male 22.0 1 0 7.2500 S Third man True NaN Southampton no False
1 1 1 female 38.0 1 0 71.2833 C First woman False C Cherbourg yes False
2 1 3 female 26.0 0 0 7.9250 S Third woman False NaN Southampton yes True
508 0 3 male 28.0 0 0 22.5250 S Third man True NaN Southampton no True
509 1 3 male 26.0 0 0 56.4958 S Third man True NaN Southampton yes True
510 1 3 male 29.0 0 0 7.7500 Q Third man True NaN Q NaN NaN
# 自定义的调色板
color = ['#dc2624', '#2b4750', '#45a0a2', '#e87a59',
         '#7dcaa9', '#649E7D', '#dc8018', '#C89F91', 
         '#6c6d6c', '#4f6268', '#c7cccf']

sns.set_palette( color )
sns.palplot( sns.color_palette(color,11) )

Python可视化——Matplotlib & Seaborn

plt.figure(figsize=(16,9))

# 条形图
plt.subplot(231)
sns.barplot( x='sex', y='survived', hue='class',hue_order= ['First', 'Second', 'Third'], data=titanic )
plt.title("条形图 barplot")

# 计数图
plt.subplot(232)
sns.countplot( x='deck',data=titanic )
plt.title("计数图 countplot")

# 点图
plt.subplot(233)
sns.pointplot( x='class',
               y='survived',
               hue='sex',
               data=titanic,
               markers=['^','o'],
               linestyles=['-','--'] )
plt.title("点图 pointplot")

# 箱型图
plt.subplot(234)
sns.boxplot( x='alive',
             y='age',
             hue='adult_male',
             data=titanic )
plt.title("箱型图 boxplot")

# 小提琴图
plt.subplot(235)
sns.violinplot( x='sex',
                y='age',
                hue='survived',
                data=titanic )
plt.title("小提琴图 violinplot")


# plt.tight_layout()  # 调整每隔子图之间的距离
plt.subplots_adjust(wspace =0.3, hspace =0.3)
plt.show()

Python可视化——Matplotlib & Seaborn


# 箱形水平图
sns.boxplot( data=iris_data, orient='h' )
<matplotlib.axes._subplots.AxesSubplot at 0x1ff99852cf8>

Python可视化——Matplotlib & Seaborn

# 双变量分布
sns.jointplot( 'sepal_length', 'sepal_width',
                data=iris_data,
                kind='kde')
<seaborn.axisgrid.JointGrid at 0x1ff9a02ee80>

Python可视化——Matplotlib & Seaborn

sns.jointplot( 'sepal_length', 'sepal_width',
                data=iris_data,
                kind='reg')
<seaborn.axisgrid.JointGrid at 0x1ff97b3ee48>

Python可视化——Matplotlib & Seaborn

6. 总结

  • 了解 Matplotlib 的绘图逻辑,以及里面包含的画图元素以及它们之间的层级。

  • 深度学 Matplotlib,只研究折线图,通过研究它的属性,一步步改进图的尺寸、像素、线条颜色宽度风格、坐标轴边界、刻度标签、图例、多图、多坐标系、标注、透明度等等,画出了一幅美图。

  • 广度学 Matplotlib,通过数据的分布、联系、比较和构成研究了直方图、散点图、折线图和饼状图,最后还为用户着想 (习惯、色盲等等) 画出更能有效表达信息的图。

  • Seaborn 就是 Matplotlib 的升级版,底层绘图逻辑和元素层级相同

    • Seaborn 比 Matplotlib 强大的三个地方就是:

      • 代码简单,基本都是一句话 (one-liner) 就可以画出变量之间统计关系图
      • 能够处理分类 (categorical) 变量 (不仅仅只能处理连续变量)
      • 颜色更加丰富好看 (不过这个看个人喜好)



本文综合整理自 传送门

上一篇:NodeJS用Express建立project


下一篇:python之matloplib可视化