查看原文
其他

matplotlib 硬核总结:乌森数据可视化系列

The following article is from 一个数据人的自留地 Author 乌森

一. matplotlib系列

Matplotlib是Python中最常用的可视化工具之一, 它比较底层,可定制性强、图表资源丰富。

1.1Matplotlib三层结构

1)容器层

容器层主要由Canvas、Figure、Axes组成。Canvas是位于最底层的,在绘图的过程中充当画板的角色,即放置画布(Figure)的工具。Figure是Canvas上方的第一层,也是用户可操作的最低层级,在绘图过程中充当画布的角色。Axes是Canvas上方的第二层,在绘图过程总相当于画布上的绘图区的角色。

  • 画板层Canvas

  • 画布层Figure(可指定画布属性,大小、清晰度等)

  • 绘图区/坐标系(可指定多区域、坐标系显示,通过figure、axes对象)

2)辅助显示层
辅助显示层用于增加相关显示功能、描述。

  • 修改x、y轴刻度(plt.x/yticks())

  • 添加描述信息(plt.x/ylabel();plt.title())

  • 添加网格(plt.grid())

3)图像层
具体描绘的图像(例如各种常见图表)。

1.2Matplotlib绘图步骤

step 1:准备数据step 2:创建一个画布(figure)step 3:在画布上创建一个或多个绘图区域(坐标系/轴,axes)step 4:绘制图像(根据不同图像类别调用不同方法)step 5:辅助绘制(刻度、图例等)step 6:图像显示/保存

import matplotlib.pyplot as plt
import random

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

if __name__ == '__main__':
    # 准备数据
    x = range(60)
    y_shanghai = [random.uniform(1518for i in x]

    # 创建画布
    plt.figure(figsize=(208), dpi=80)

    # 创建绘图区域
    ax = plt.subplot(111)
    ax.set_xlabel("时间变化")
    ax.set_ylabel("温度变化")
    ax.set_title("某城市11点到12点温度变化")

    # 绘制图像
    ax.plot(x, y_shanghai, color='b', linestyle='--', label='上海')

    # 辅助绘制:显示图例
    ax.legend()

    # 辅助绘制:准备x、y的刻度以及刻度说明
    x_label = ["11点{}分".format(i) for i in x]
    ax.set_xticks(x[::5], x_label[::5])
    ax.set_yticks(range(0405))

    # 辅助绘制:添加网格
    ax.grid(linestyle='--', alpha=0.5)

    plt.show()

1.3  其他注意事项

1)绘图风格

print(plt.style.available)
plt.style.use('seaborn-paper')

2)显示问题

Matplotlib默认情况中文和负号不能正常显示,可以更改如下配置来解决。

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

matplotlib 颜色、标记、线型:https://blog.csdn.net/qq_41455420/article/details/79733524
matplotlib 坐标轴与刻度:https://blog.csdn.net/wuzlun/article/details/80053277
matplotlib中文文档:
https://www.matplotlib.org.cn/

二. 多子图绘制功能

在matplotlib下,一个画布(Figure)对象可以包含多个子图(Axes),可以使用subplot()快速绘制。

2.1subplot介绍

subplot(numRows, numCols, plotNum)

图表的整个绘图区域被分成numRows行和numCols列,plotNum参数指定创建的Axes对象所在的区域。

2.2  subplot应用举例

import matplotlib.pyplot as plt
import numpy as np
def f(t):
    return np.exp(-t) * np.cos(2 * np.pi * t)

t1 
= np.arange(050.1)
t2 = np.arange(050.02)

fig = plt.figure(figsize=(1610), dpi= 80)  # 画布

ax1 = plt.subplot(221)  # 两行两列中的第一行第一列位置
ax1.plot(t1, f(t1), 'bo', t2, f(t2), 'r--')
 
ax2 = plt.subplot(222)  # 两行两列中的第一行第二列位置
ax2.plot(t2, np.cos(2 * np.pi * t2), 'r--')
 
ax3 = plt.subplot(212)  # 两行一列中的第二行的位置
ax3.plot([1234], [14916])

plt.show()


三. 绘制二维图表

matplotlib提供了常见二维图表的绘制。

3.1数据分布

1)直方图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_hist(title, x):
    '''
    绘制直方图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴设定
    plt.title(title, fontsize=22)
    plt.xlabel('x', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.ylabel('y', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 设置坐标轴刻度线
    # plt.yticks([1,5,8,15,24], [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$'])

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    # ax.set_aspect('
equal')  # 坐标轴等比例
    ax.xaxis.set_tick_params(labelsize=16, colors='g') # 坐标轴刻度格式
    ax.xaxis.set_major_locator(plt.MultipleLocator(1)) # 坐标轴刻度间隔1
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 移动坐标轴
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data'0))  # 将bottom即是x坐标轴设置到y=0的位置
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data'0))  # 将left即是y坐标轴设置到x=0的位置

    # 消除边框
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
    ax.hist(x,
            bins=25,  # 分段数量
            width=0.2,   # 宽度
            alpha=0.5,   # 不透明度
            #facecolor='white',  # 柱形填充颜色
            #hatch='/',   # 图形填充形状,可选['/''', '|', '-', '+', 'x''o''O''.''*']
            #edgecolor='darkblue'  # 边缘颜色
            )
    
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = np.random.normal(0,1,1000)
plot_hist('测试图', x)

如果只需要简单的计算每段区间的样本数,而并不想画图显示它们,那么可以直接用np.histogram()

import numpy as np

x = np.random.normal(0,1,1000)
counts, bin_edges = np.histogram(x, bins=50)
print(counts)

2)箱形图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_box(title, data, labels):
    '''
    绘制箱形图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴设定
    plt.title(title, fontsize=22)
    plt.ylabel('y', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    ax.xaxis.set_tick_params(labelsize=16)
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 消除边框
    ax.spines['left'].set_color('none')
    ax.spines['bottom'].set_color('none')
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
    bplot = ax.boxplot(data,
               widths=0.2,   # 设置箱体宽度
         patch_artist=True, # 箱体是否染色
         notch=False,  # 中位线处不设置凹陷
               medianprops={'linestyle':'--','color':'green','markerfacecolor':'indianred''markersize':4},  # 设置均值点的属性, 如点的形状、填充色和点的大小
               # flierprops={'marker':'o','markerfacecolor':'red''markersize':3},  # 设置异常点属性, 如点的形状、填充色和点的大小
               labels=labels   # 标签
               )
    colors =["pink""lightgreen","pink""lightgreen"]
    for i, item in enumerate(bplot["boxes"]):
        item.set_facecolor(colors[i])

    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

data = [
        [1000120013001400150016001700180019002500],
        [1200130014001500160017001800190020002100],
        [1000120013001400150016001700180019002000],
        [800100012001300140015001600170018001900]
    ]
labels =["China","America","Britain","Russia"]

plot_box('测试图', data, labels)

3)小提琴图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_violin(title, data, labels):
    '''
    绘制小提琴图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴设定
    plt.title(title, fontsize=22)
    plt.ylabel('y', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    ax.xaxis.set_tick_params(labelsize=16)
    ax.set_xticks([i+1 for i in range(len(data))]) 
    ax.set_xticklabels([labels[i] for i in range(len(data))])
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 消除边框
    ax.spines['left'].set_color('none')
    ax.spines['bottom'].set_color('none')
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
    vplot = ax.violinplot(data, 
               vert=True,   # 是否竖直显示
               showmedians=True,  # 显示中位数
               showmeans=False  # 显示平均数
               )
    for item, color in zip(vplot['bodies'], ['cyan''red''blue''green''purple']):
        item.set(facecolor=color, alpha=0.5)
    for item in ['cbars''cmaxes''cmins''cmedians']:
        plt.setp(vplot[item], edgecolor='gray', linewidth=1.5)
        plt.setp(vplot['cmedians'], edgecolor='black')

    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

data = [
        [1000120013001400150016001700180019002500],
        [1200130014001500160017001800190020002100],
        [300120013001400150016001700180019002000],
        [800100012001300140015001600170018001900]
    ]
labels =["China","America","Britain","Russia"]

plot_violin('测试图', data, labels)

3.2  数据比较

1)柱形图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_bar(title, x, y):
    '''
    绘制柱形图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴和标签设定
    plt.title(title, fontsize=22)
    plt.xlabel('xlabel', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.xlim(-15)
    plt.ylabel('ylabel', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.ylim(-230)

    # 设置坐标轴刻度线
    plt.yticks([1,5,8,15,24], [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$'])

    # 是否显示网格
    ax.grid(False)
       
    # 坐标轴的一些属性设定
    # ax.set_aspect('
equal')  # 坐标轴等比例
    ax.xaxis.set_tick_params(labelsize=16, colors='g') # 坐标轴刻度格式
    ax.xaxis.set_major_locator(plt.MultipleLocator(1)) # 坐标轴刻度间隔1
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 移动坐标轴
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data'0))  # 将bottom即是x坐标轴设置到y=0的位置
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data'0))  # 将left即是y坐标轴设置到x=0的位置

    # 消除边框
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
 &nnbsp;  rects = ax.bar(x, y,
                   width=0.5,   # 宽度
                   alpha=0.5,   # 不透明度
                   #facecolor='white',  # 柱形填充颜色
                   #hatch='/',   # 图形填充形状,可选['/''', '|', '-', '+', 'x''o''O''.''*']
                   #edgecolor='darkblue'  # 边缘颜色
                   )
    # 为柱状图添加高度值
    for rect in rects:
        x = rect.get_x()
        height = rect.get_height()
        ax.text(x+0.21.01*height, str(height), fontsize=16)
   
    # plt.legend(fontsize=16, loc='upper right')  # 标签设定
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = np.arange(151)
y = np.array([15,20,18,25])
plot_bar('测试图', x, y)

2)雷达图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_radar(title, p1, p2):
    '''
    绘制雷达图
    '''
    fig = plt.figure(figsize=(10,5))
    ax1 = fig.add_subplot(121, polar=True) # 坐标轴为极坐标体系
    ax2 = fig.add_subplot(122, polar=True)
    fig.subplots_adjust(wspace=0.4)  # 设置子图间的间距为子图宽度的40%

    data1 = np.array([i for i in p1.values()]).astype(int)
    data2 = np.array([i for i in p2.values()]).astype(int)
    label = np.array([j for j in p1.keys()]) # 提取标签

    angle = np.linspace(02*np.pi, len(data1), endpoint=False) # data里有几个数据,就把整圆360°分成几份
    angles = np.concatenate((angle, [angle[0]])) # 增加第一个angle到所有angle里,以实现闭合

    data1 = np.concatenate((data1, [data1[0]])) # 增加第一组数据的第一个值到第一组数据所有的值里,以实现闭合
    data2 = np.concatenate((data2, [data2[0]])) # 增加第二组数据的第一个值到第二组数据所有的值里,以实现闭合

    # 设置第一个坐标轴
    ax1.set_thetagrids(angles*180/np.pi, label) # 设置网格标签
    ax1.plot(angles,data1,"o-")
    ax1.set_theta_zero_location('NW') # 设置极坐标0°位置
    ax1.set_rlim(0,100) # 设置显示的极径范围
    ax1.fill(angles,data1,facecolor='g', alpha=0.2) # 填充颜色
    ax1.set_title("甲",fontproperties="SimHei",fontsize=16) # 设置标题

    # 设置第二个坐标轴
    ax2.set_thetagrids(angles*180/np.pi, label) # 设置网格标签
    ax2.plot(angles,data2,"o-")
    ax2.set_theta_zero_location('NW')  #设置极坐标0°位置
    ax2.set_rlim(0,100)  # 设置显示的极径范围
    ax2.fill(angles,data2,facecolor='g', alpha=0.2) # 填充颜色
    ax2.set_title("乙",fontproperties="SimHei",fontsize=16) # 设置标题

    plt.show()

p1={"编程能力":60,"沟通技能":70,"专业知识":65,"团体协作":75,"工具掌握":80} #创建第一个人的数据
p2={"编程能力":70,"沟通技能":60,"专业知识":75,"团体协作":65,"工具掌握":70} #创建第二个人的数据
plot_radar('测试图', p1, p2)

3)折线图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_line(title, x, y):
    '''
    绘制折线图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴设定
    plt.title(title, fontsize=22)
    plt.xlabel('x', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.ylabel('y', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 设置坐标轴刻度线
    # plt.yticks([1,5,8,15,24], [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$'])

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    # ax.set_aspect('
equal')  # 坐标轴等比例
    ax.xaxis.set_tick_params(labelsize=16, colors='g') # 坐标轴刻度格式
    ax.xaxis.set_major_locator(plt.MultipleLocator(5)) # 坐标轴刻度间隔5
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 移动坐标轴
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data'0))  # 将bottom即是x坐标轴设置到y=0的位置
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data'0))  # 将left即是y坐标轴设置到x=0的位置

    # 消除边框
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
    ax.plot(x, y,
            linewidth = 3, # 线宽
            linestyle=':', # 线的风格(-是实线,:是虚线)
            alpha=0.5,   # 不透明度
            color='black',  # 折线颜色
            label='a'   # 标签
            )
    
    plt.legend(fontsize=16, loc='upper right')  # 标签设定
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = np.arange(50)
y = x**2+4
plot_line('测试图', x, y)

3.3数据关系

1)散点图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_scatter(title, x, y):
    '''
    绘制散点图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴设定
    plt.title(title, fontsize=22)
    plt.xlabel('x', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.ylabel('y', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 设置坐标轴刻度线
    # plt.yticks([1,5,8,15,24], [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$'])

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    ax.set_aspect('
equal')  # 坐标轴等比例
    ax.xaxis.set_tick_params(labelsize=16) # 坐标轴刻度格式
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 移动坐标轴
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data'0))  # 将bottom即是x坐标轴设置到y=0的位置
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data'0))  # 将left即是y坐标轴设置到x=0的位置

    # 消除边框
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
    ax.scatter(x, y, 
               alpha =0.8  # 不透明度
               )
    
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = np.random.random(100)*10
y = np.random.random(100)*10
plot_scatter('测试图', x, y)

2)气泡图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_bubble(title, x, y, s):
    '''
    绘制气泡图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴和标签设定
    plt.title(title, fontsize=22)
    plt.xlabel('x', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.ylabel('y', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 设置坐标轴刻度线
    # plt.yticks([1,5,8,15,24], [r'$really\ bad$',r'$bad$',r'$normal$',r'$good$',r'$really\ good$'])

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    ax.set_aspect('
equal')  # 坐标轴等比例
    ax.xaxis.set_tick_params(labelsize=16) # 坐标轴刻度格式
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 移动坐标轴
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data'0))  # 将bottom即是x坐标轴设置到y=0的位置
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data'0))  # 将left即是y坐标轴设置到x=0的位置
    
    # 消除边框
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    # 绘图
    ax.scatter(x, y, 
               s=s, # 点的面积
               c=np.random.choice(['red','blue'], 100),  # 点的颜色
               alpha =0.8  # 不透明度
               )
    
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = np.random.random(100)*10
y = np.random.random(100)*10
s = np.random.random(100)*300 # 点的面积
plot_bubble('测试图', x, y, s)

3.4  数据成分

1)饼图

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_pie(title, sizes, labels, explode):
    '''
    绘制饼图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题设定
    plt.title(title, fontsize=22)

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    ax.set_aspect('equal')  # 坐标轴等比例

    # 绘图
    ax.pie(sizes,  # 百分比(list)
           autopct='%1.1f%%', # 百分比显示设置
           labels=labels,  # (每一块)饼图外侧显示的说明文字
           startangle=150, # 开始绘制的角度
           explode=explode,  # (每一块)离开中心距离
           shadow=False  # 在饼图下面画一个阴影。默认值:False,即不画阴影
           )
    
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

sizes = [2,5,12,70,2,9]
labels = ['娱乐','育儿','饮食','房贷','交通','其它']
explode = (0,0,0,0.1,0,0)
plot_pie('饼图示例-某家庭支出', sizes, labels, explode)

2)堆积柱形图

#-*- coding:utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

# print(plt.style.available)
plt.style.use('seaborn-paper')

def plot_stackedbar(title, x, ys):
    '''
    绘制堆积柱形图
    '''
    fig, ax = plt.subplots(figsize=(16,10), dpi= 80) # 创建一个画板

    # 标题、坐标轴设定
    plt.title(title, fontsize=22)
    plt.xlabel('xlabel', fontsize=16, fontfamily='sans-serif',fontstyle='italic')
    plt.ylabel('ylabel', fontsize=16, fontfamily='sans-serif',fontstyle='italic')

    # 是否显示网格
    ax.grid(False)

    # 坐标轴的一些属性设定
    # ax.set_aspect('equal')  # 坐标轴等比例
    ax.xaxis.set_tick_params(labelsize=16, colors='g') # 坐标轴刻度格式
    ax.yaxis.tick_right() # y轴坐标布局位置
    ax.yaxis.set_tick_params(labelsize=16)

    # 消除边框
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    t = 0
    for y, c, label in zip(ys, ['r''g''c'], ['label1''label2''label3']):
        plt.bar(x, y, width=0.2, bottom=t, color=c, label=label)
        t += y

    plt.legend(fontsize=16, loc='upper right')  # 标签设定
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = np.linspace(0520)
y1 = np.random.randint(5010020)
y2 = np.random.randint(5010020)
y3 = np.random.randint(5010020)
plot_stackedbar('测试图', x, [y1,y2,y3])

50张matplotlib图表:
https://www.machinelearningplus.com/plots/top-50-matplotlib-visualizations-the-master-plots-python/

四. 绘制三维图表

matplotlib绘制三维图表主要通过mplot3d模块实现,但由于三维图表实际上是在二维画布上展示,因此同样需要载入pyplot模块。

matplotlib绘制三维图表主要通过mplot3d模块实现,但由于三维图表实际上是在二维画布上展示,因此同样需要载入pyplot模块。
1)三维空间中的点

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

def plot_scatter_3d(title, x, y, z):
    '''
    绘制3D散点图
    '''
    fig = plt.figure(figsize=(1610), dpi= 80) # 创建一个画板
    ax = Axes3D(fig)
    ax.scatter(xs=x, 
               ys=y, 
               zs=z, 
               c='r',  # 颜色
               marker='o', # 点的标记
               label='positive' # 标签
               )

    # 设置坐标轴显示以及旋转角度
    ax.set_xlabel('x', fontsize=16)
    ax.set_ylabel('y', fontsize=16)
    ax.set_zlabel('z', fontsize=16)
    ax.view_init(elev=10, azim=235)

    plt.title(title, fontsize=22)
    plt.grid(False)   # 是否显示网格
    ax.set_aspect('equal')  # 坐标轴间比例一致
    ax.legend(loc='upper left', fontsize=16)
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

x = (40 - 15) * np.random.rand(100) + 15
y = (25 - 5) * np.random.rand(100) - 5
z = (15 - 4) * np.random.rand(100) + 4
plot_scatter_3d('测试图', x, y, z)

2)三维空间中的线

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

def plot_line_3d(title, x, y, z):
    '''
    绘制3D折线图
    '''
    fig = plt.figure(figsize=(1610), dpi= 80) # 创建一个画板
    ax = Axes3D(fig)
    ax.plot(xs=x,
            ys=y, 
            zs=z, 
            c='r',  # 颜色
            label='parametric curve' # 标签
            )

    # 设置坐标轴显示以及旋转角度
    ax.set_xlabel('x', fontsize=16)
    ax.set_ylabel('y', fontsize=16)
    ax.set_zlabel('z', fontsize=16)
    ax.view_init(elev=10, azim=235)

    plt.title(title, fontsize=22)
    plt.grid(False)   # 是否显示网格
    ax.set_aspect('equal')  # 坐标轴间比例一致
    ax.legend(loc='upper left', fontsize=16)
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

z = np.linspace(-22100
r = np.linspace(-22100) ** 2 + 1
x = r * np.sin(np.linspace(-8 * np.pi, 8 * np.pi, 100))  # [-5,5]
y = r * np.cos(np.linspace(-8 * np.pi, 8 * np.pi, 100))  # [-5,5]
plot_line_3d('测试图', x, y, z)

3)三维空间中的面

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

def plot_surface_3d(title, x, y, z):
    '''
    绘制3D曲面图
    '''
    fig = plt.figure(figsize=(1610), dpi= 80) # 创建一个画板
  nbsp;  ax = Axes3D(fig)
    ax.plot_surface(X=x, 
                    Y=y, 
                    Z=z
                    )

    # 设置坐标轴显示以及旋转角度
    ax.set_xlabel('x', fontsize=16)
    ax.set_ylabel('y', fontsize=16)
    ax.set_zlabel('z', fontsize=16)
    ax.view_init(elev=10, azim=235)

    plt.title(title, fontsize=22)
    plt.grid(False)   # 是否显示网格
    ax.set_aspect('equal')  # 坐标轴间比例一致
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

# 生成[-5,5]间隔0.25的数列,间隔越小,曲面越平滑
x = np.arange(-550.25)    
y = np.arange(-550.25)
# 格点矩阵,原来的x行向量向下复制len(y)次,形成len(y)*len(x)的矩阵,即为新的x矩阵;
# 原来的y列向量向右复制len(x)次,形成len(y)*len(x)的矩阵,即为新的y矩阵;新的x矩阵和新的y矩阵shape相同
x, y = np.meshgrid(x,y)
r = np.sqrt(x ** 2 + y ** 2)
z = np.sin(r)
plot_surface_3d('测试图', x, y, z)

4)三维空间中的体

#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False 

def plot_body_3d(title, verts, faces):
    '''
    绘制3D实体图
    '''
    fig = plt.figure(figsize=(1610), dpi= 80) # 创建一个画板
    ax = Axes3D(fig)

    # 获得每个面的顶点
    poly3d = [[verts[vert_id] for vert_id in face] for face in faces]
    # 绘制顶点
    x, y, z = zip(*verts)
    ax.scatter(x, y, z)

    # 绘制多边形面
    ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.3))
    # 绘制多边形的边
    ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

    # 设置坐标轴显示以及旋转角度
    ax.set_xlabel('x', fontsize=16)
    ax.set_ylabel('y', fontsize=16)
    ax.set_zlabel('z', fontsize=16)
    ax.view_init(elev=10, azim=235)

    plt.title(title, fontsize=22)
    plt.grid(False)   # 是否显示网格
    ax.set_aspect('equal')  # 坐标轴间比例一致
    # plt.savefig("./"+title+".png") # 保存图片
    plt.show()

# 六面体顶点和面
verts = [(000), (010), (110), (100), (001), (011), (111), (101)]
faces = [[0123], [4567], [0154], [1265], [2376], [0374]]

# 四面体顶点和面
# verts = [(000), (100), (110), (101)]
# faces = [[012], [013], [023], [123]]

plot_body_3d('测试图', verts, faces)

五. 高级封装

seaborn是对matplotlib更高级的API封装,让你能用更少的代码去调用 matplotlib的方法,从而使得作图更加容易。

5.1分布图

1)核密度估计图

单变量核密度估计图:

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

mean, cov = [02], [(1.5), (.51)]
x, y = np.random.multivariate_normal(mean, cov, size=50).T

sns.kdeplot(x,
            shade=True, 
            shade_lowest=False)

plt.show()

代码片段:可切换语言,无法单独设置文字格式

双变量核密度估计图:

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])
d["species"] = iris.target

d.loc[d["species"]==0"species"] = "setosa"  # 把类别这一列数值为0的替换为setosa
d.loc[d["species"]==1"species"] = "versicolor"  # 把类别这一列数值为1的替换为versicolor
d.loc[d["species"]==2"species"] = "virginica"  # 把类别这一列数值为2的替换为virginica

sns.kdeplot(d.sepal_length[d.species=="setosa"], 
            d.sepal_width[d.species=="setosa"],
            cmap="Reds"
            shade=True, 
            shade_lowest=False)
sns.kdeplot(d.sepal_length[d.species=="versicolor"], 
            d.sepal_width[d.species=="versicolor"],
            cmap="Blues"
            shade=True, 
            shade_lowest=False)
plt.show()

2)联合分布图
联合概率分布简称联合分布,是两个及以上随机变量组成的随机向量的概率分布。

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])
d["species"] = iris.target

d.loc[d["species"]==0"species"] = "setosa"  # 把类别这一列数值为0的替换为setosa
d.loc[d["species"]==1"species"] = "versicolor"  # 把类别这一列数值为1的替换为versicolor
d.loc[d["species"]==2"species"] = "virginica"  # 把类别这一列数值为2的替换为virginica

sns.jointplot(d.sepal_length, 
              d.sepal_width,
              data=d,
              kind='kde',  # scatter|reg|resid|kde|hex
              dropna=True)
plt.show()

3)变量关系组图

变量关系组图非常有用,人们经常用它来查看多个变量之间的联系。

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])
d["species"] = iris.target

d.loc[d["species"]==0"species"] = "setosa"  # 把类别这一列数值为0的替换为setosa
d.loc[d["species"]==1"species"] = "versicolor"  # 把类别这一列数值为1的替换为versicolor
d.loc[d["species"]==2"species"] = "virginica"  # 把类别这一列数值为2的替换为virginica

sns.pairplot(d, hue="species")
plt.show()

seaborn分布数据可视化:
https://blog.csdn.net/qq_42554007/article/details/82625118

5.2回归图

简单线性回归的模型非常容易拟合。

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])
d["species"] = iris.target

d.loc[d["species"]==0"species"] = "setosa"  # 把类别这一列数值为0的替换为setosa
d.loc[d["species"]==1"species"] = "versicolor"  # 把类别这一列数值为1的替换为versicolor
d.loc[d["species"]==2"species"] = "virginica"  # 把类别这一列数值为2的替换为virginica

sns.lmplot(x="sepal_length",
           y="sepal_width",
           data=d[d.species == "setosa"])
plt.show()

多项式回归模型可以拟合数据集中的一些简单的非线性趋势。

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])
d["species"] = iris.target

d.loc[d["species"]==0"species"] = "setosa"  # 把类别这一列数值为0的替换为setosa
d.loc[d["species"]==1"species"] = "versicolor"  # 把类别这一列数值为1的替换为versicolor
d.loc[d["species"]==2"species"] = "virginica"  # 把类别这一列数值为2的替换为virginica

sns.lmplot(x="sepal_length",
           y="sepal_width"
           hue="species"
           data=d,
           order=2, # 二阶多项式
           ci=None, 
           scatter_kws={"s"80})
plt.show()

5.3  矩阵图

1)热图

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])
d["species"] = iris.target

d.loc[d["species"]==0"species"] = "setosa"  # 把类别这一列数值为0的替换为setosa
d.loc[d["species"]==1"species"] = "versicolor"  # 把类别这一列数值为1的替换为versicolor
d.loc[d["species"]==2"species"] = "virginica"  # 把类别这一列数值为2的替换为virginica

sns.heatmap(d.corr(), 
            xticklabels=d.corr().columns, 
            yticklabels=d.corr().columns, 
            cmap='RdYlGn'
            center=0
            annot=True)

plt.show()

2)聚类图

import imp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
d = pd.DataFrame(iris.data, columns=["sepal_length","sepal_width","petal_length","petal_width"])

sns.clustermap(d)

plt.show()


- EOF -


推荐阅读  点击标题可跳转

1、Python 绘图库 Matplotlib 入门教程

2、这 30 个细节,决定了数据可视化的质量

3、精选 10 个 Python 可视化工具,请查收!


看完本文有收获?请转发分享给更多人

推荐关注「数据分析与开发」,提升数据技能

点赞和在看就是最大的支持❤️

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存