目录
一、Matplotlib 数据可视化基础
1. Matplotlib 认识
Matplotlib 是一个 Python 的 2D 绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。
他的作用就是将数据可视化
2.Matplotlib 绘图流程
二、入门案例
案例1:(气象图)
现在人们对于旅游、出行越来越热衷,一旦出现周末、小假期,基本都会出行旅游,所
以对于天气的依赖越来越重要,以 xx 城市下一周天气温度走势为例,来理解绘图三部曲,
以下为某城市下一周天气温度表:
绘图后效果:
import matplotlib.pyplot as plt
import numpy as np
# 绘图三部曲
# (1)创建画布
# 参数: figsize ---画布大小
# 参数: dpi ---像素
# 返回值: 返回画布对象
plt.figure()
# (2)绘制图形
# 绘制下一周天气走势---折线图
# 折线图---要素:点 ---坐标轴:x,y坐标 ---(x,y)
# 绘制折线图的时候---准备 (x1,y1) (x2,y2) (x3,y3) ....
# 绘制折线图的时候,不需要配对xy---只需要准备好一个x数组,一个y的数组
# 横轴---周一、周二、 ...、周日
# 纵轴---不同的温度
# 如果横轴是中文,一般先用序号代替,后续再进行将序号替换为中文
x = np.arange(1, 8)
y = np.array([15, 20, 22, 23, 20, 18, 16])
print('x:\n', x)
print('y:\n', y)
# 绘制
plt.plot(x,y)
# (3)图形展示
plt.show()
案例2:(气象图-图形修饰)
效果图:
import matplotlib.pyplot as plt
import numpy as np
# 绘图三部曲
# (1)创建画布
# 参数: figsize ---画布大小
# 参数: dpi ---像素
# 返回值: 返回画布对象
plt.figure()
# 默认不支持中文
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘制图形
# 绘制下一周天气走势---折线图
# 折线图---要素:点 ---坐标轴:x,y坐标 ---(x,y)
# 绘制折线图的时候---准备 (x1,y1) (x2,y2) (x3,y3) ....
# 绘制折线图的时候,不需要配对xy---只需要准备好一个x数组,一个y的数组
# 横轴---周一、周二、 ...、周日
# 纵轴---不同的温度
# 如果横轴是中文,一般先用序号代替,后续再进行将序号替换为中文
x = np.arange(1, 8)
y_bj = np.array([15, 20, 22, 23, 20, 18, 16])
y_heb = np.array([-10, -8, -12, -10, -8, -6, 1])
print('x:\n', x)
print('y_bj:\n', y_bj)
print('y_heb:\n', y_heb)
# color --线的颜色
# linestyle --线的样式
# linewidth --线的宽度
# marker --点的样式
# markersize --点的大小
# markerfacecolor --点的填充颜色
# markeredgecolor --点的边缘颜色
# 绘制
plt.plot(x, y_bj, color='r', linestyle=':', linewidth=1.2, marker="*", markersize=7, markerfacecolor='b',
markeredgecolor='g')
plt.plot(x, y_heb, color='#2F4F4F', linestyle='-.', linewidth=1.2, marker="d", markersize=7, markerfacecolor='r',
markeredgecolor='r')
# 增加标题
plt.title('北京、哈尔滨下一周天气温度走势图')
# 修改横轴名称
plt.xlabel('日期')
# 修改纵轴名称
plt.ylabel('温度/℃')
# 将横轴的序号 替换为中文 --修改横轴刻度
# 注意:如果修改的时候,是将序号替换为中
# 参数1 :需要被替换的序号
# 参数2 :替换之后的中文
# 构建中文日期列表
xticks = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
# rotation=45 旋转角度
plt.xticks(x, xticks, rotation=45)
# 修改纵轴刻度
# 重新设置新的显示的刻度范围
# 注意:只需要将新的刻度范围传递进去
# 并不改变真实点的纵坐标,只是修改其显示位置
yticks = np.arange(-15, 31, 3)
plt.yticks(yticks)
# 增加图例
# loc 图例的位置
plt.legend(['北京', '哈尔滨'], loc=4)
# 标注
# plt.text ---一次标注一个点
# 循环标注
for i, j in zip(x, y_bj): # zip打包函数
# i 点的横坐标
# j 点的纵坐标
# 参数1 标注的横坐标
# 参数2 标注的纵坐标
# 参数3 标注的内容---str
plt.text(i, j + 1, '%d℃' % j,
horizontalalignment='center', # 水平居中
# verticalalignment='bottom' # 点的底部
)
for i, j in zip(x, y_heb): # zip打包函数
# i 点的横坐标
# j 点的纵坐标
# 参数1 标注的横坐标
# 参数2 标注的纵坐标
# 参数3 标注的内容---str
plt.text(i, j + 1, '%d℃' % j,
horizontalalignment='center', # 水平居中
# verticalalignment='bottom' # 点的底部
)
# 将图片进行保存
plt.savefig('./北京、哈尔滨下一周天气温度走势图.png')
# (3)图形展示
plt.show()
案例3:(散点图)
效果图:
实现代码:
import numpy as np
import matplotlib.pyplot as plt
# 加载数据
res = np.load('./国民经济核算季度数据.npz')
# columns values
# 获取数组
columns = res['columns']
values = res['values']
# 打印数据
print('columns:\n', columns)
print('values:\n', values)
# (1)创建画布
plt.figure(figsize=(14, 12), dpi=100)
# 默认不支持中文
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# 为了演示 更改颜色--特地选择一些高亮的颜色
# 选择合适的颜色
# # 设置横轴、纵轴刻度颜色
# plt.rcParams['xtick.color'] = '#7FFF00'
# plt.rcParams['ytick.color'] = '#7FFF00'
# # 设置边框颜色
# plt.rcParams['axes.edgecolor'] = '#EE9A00'
# # 设置背景颜色
# plt.rcParams['axes.facecolor'] = '#FFE4C4'
# # 设置保存的画布的颜色
# plt.rcParams['savefig.facecolor'] = '#8DEEEE'
# (2)绘制图形
# 散点图---2000-2017各个产业增加总值散点图
# 散点图---要素:点 ----要素:x,y坐标
# 准备多个点----(x1,y1) (x2,y2) .....----不需要
# 需要准备 x 数组
# 需要准备 y 数组
x = np.arange(0, values.shape[0], 4)
# 第一产业
y1 = values[:, 3][::4]
# 第二产业
y2 = values[:, 4][::4]
# 第三产业
y3 = values[:, 5][::4]
# 绘制散点图
# s--点的大小--可以传具体的数值---这一组所有的点的大小都是一样
# 传递一个数组---表示这一组各个点的大小
# c--点的颜色 --可以传具体的颜色---这一组所有的点的颜色都是一致的
# 传递一个数组---表示这一组各个点的颜色
# marker --点的样式---接收特定的字符串,表示这一组所有点的样式
# alpha ---透明度---[0,1]--值越大,越凝实,值越小,越透明
plt.scatter(x, y1, s=60, marker='*', c='r', alpha=0.8)
plt.scatter(x, y2, s=60, marker='d', c='g', alpha=0.8)
plt.scatter(x, y3, s=60, marker='o', c='k', alpha=0.8)
# 修饰
# 增加标题
plt.title('2000-2017年各个产业增加总值散点图', fontsize='large')
# 增加横轴名称
plt.xlabel('时间', fontsize='large')
# 增加纵轴名称
plt.ylabel('生产总值(亿元)', fontsize='large')
# 修改横轴刻度
plt.xticks(x[::4], values[:, 1][::4], rotation=45, fontsize='large')
# 构建图例
legend = [tmp[:4] for tmp in columns[3:6]]
# 增加图例
plt.legend(legend, loc=2, fontsize='large')
# 保存图形
plt.savefig('./2000-2017年各个产业增加总值散点图.png')
# (3)图形展示
plt.show()
# 散点图的应用场景:
# 可以连接成折线的散点图,可以适用于观察数据的发展趋势
# 也可以用来查看数据的分布情况
案例4:(柱状图)
效果图:
# 柱状图: ---由高低不同的额柱子组成,不同的柱子具有不同的含义,一般柱子之间存在间隙
# 一般情况下的柱状图,横轴代表不同的类别,纵轴代表不同类别所对应的数目
# 而且,横轴的分类数目不宜过多,适用于数据量较小的情况----用来对比不同的类别数据
import numpy as np
import matplotlib.pyplot as plt
# 加载数据
res = np.load('./国民经济核算季度数据.npz')
# columns values
# 获取数组
columns = res['columns']
values = res['values']
# 打印数据
print('columns:\n', columns)
print('values:\n', values)
# (1)创建画布
plt.figure()
# 默认不支持中文
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘图
# 绘制柱状图
# 2000年第一季度,第一产业、第二产业、第三产业增加总值的对比柱状图
# 准备横轴、纵轴数据
# 横轴 ---各个产业名称 ---序号
x = np.arange(1, 4)
# 纵轴 --2000年第一季度 各个产业增加总值 具体的值
y = values[0, 3:6]
# 绘制
# width 柱子的宽度
# color --接收特定颜色 ---所有柱子的颜色
# 或者颜色数组 ---各个柱子的颜色
plt.bar(x, y, width=0.5, color=['#FFDAB9', '#AFEEEE', '#F5DEB3'])
# 增加标题
plt.title('2000年第一季度各个产业增加总值对比柱状图')
# 增加横轴名称
plt.xlabel('产业')
# 增加纵轴名称
plt.ylabel('生产总值(亿元)')
# 构造刻度
xticks = [tmp[:4] for tmp in columns[3:6]]
# 修改横轴刻度
plt.xticks(x, xticks)
# 标注
for i, j in zip(x, y):
plt.text(i, j, '%.1f亿元' % j, horizontalalignment='center')
# 保存
plt.savefig('./2000年第一季度各个产业增加总值对比柱状图.png')
# (3)图形展示
plt.show()
案例5:(直方图)
效果图:
代码实现:
# 直方图---由高低不等的柱子构成的,一般柱子之间是相连的
# 横坐标----一般为不同的数据范围
# 纵坐标----数据落在各个数据范围内的数量
# 一般用于大量数据 # 直方图是用来查看数据的整体的分布状态
import matplotlib.pyplot as plt
import numpy as np
# 绘制某班级学员身高分布的直方图
# 30名学员 ---[140-190)
# 构建数据 ----身高--小数
# 随机构建
# 生成指定范围的随机小数
# 生成[low,high)范围的随机的小数数组
hight = np.random.uniform(low=140, high=190, size=30)
print('hight:\n', hight)
# 将数组保留一位小数
hight = np.array([float('%.1f' % tmp) for tmp in hight])
print('保留一位小数的身高:\n', hight)
# (1)创建画布
plt.figure()
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘图
# 绘制直方图
# 只需要传入真实的数据,再传入如何分组,那么默认将所有的数据以直方图的形式展示出来
# 此时--》传入数据,--传入分组---》自动帮助我们分组---》自动帮助我们统计落在每个组的数量---》以直方图显示出来
# 默认分组
# 参数 具体数据
# 参数 bins --->分组
# plt.hist(hight, bins=5)
# # 自定义分组 --指定分组节点
# bins = [140, 150, 160, 170, 180, 190]
# 自定义等宽分组
# (1)确定分组组数
group_num = 5
# (2)确定步长
# a、最大值
max_hight = np.max(hight, axis=0)
print('身高的最大值:', max_hight)
# b、最小值
min_hight = np.min(hight, axis=0)
print('身高的最小值:', min_hight)
# c、间距 ---???
# 先计算出具体的值--->向上取整 --->转化为整型数据
# np.ceil --向上取整
# np.floor ---向下取整
width = int(np.ceil((max_hight - min_hight) / group_num))
print('身高分布间距:', width)
# (3)确定分组的节点
# 结束位置为:max_hight + width) --->保证了最大值肯定在范围内
bins = np.arange(min_hight, max_hight + width, width)
print('分组节点:\n', bins)
plt.hist(hight, bins=bins, color='#ADD8E6', edgecolor='k', rwidth=1)
# 修改刻度
plt.xticks(bins)
# 增加网格线
# axis = 'y' 只开启y轴的网格线
# alpha 透明度 [0,1]之间
plt.grid(b=True, axis='y', alpha=0.2)
# 增加标题
plt.title('某班级同学身高分布直方图')
# 增加横轴名称
plt.xlabel('身高范围(cm)')
# 增加纵轴名称
plt.ylabel('人数(个)')
# 保存
plt.savefig('./某班级同学身高分布直方图.png')
# (3)图形展示
plt.show()
# 柱状图与直方图区别:
# (1)直方图展示数据的分布,柱状图比较数据的大小。 (2)直方图 X 轴为定量数据,柱状图 X 轴为分类数据。 (3)直方图柱子无间隔,柱状图柱子有间隔。 (4)直方图柱子宽度可不一,柱状图柱子宽度须一致。
# 绘制直方图的注意点:
# 组距---组数
案例6:(饼图)
效果图:
实现代码:
# 饼图---类似于一张‘饼’这样的图形
# 可以用来对比部分与部分的关系、对比部分与整体的关系
# plt.pie绘制饼图
# 以2017年第一季度各个产业增加总值占比 --饼图
import numpy as np
import matplotlib.pyplot as plt
# 加载数据
res = np.load('./国民经济核算季度数据.npz')
# print(res) # <numpy.lib.npyio.NpzFile object at 0x000000000210B240>
# 遍历
# for tmp in res:
# print(tmp)
# 获取对应的数组
columns = res['columns']
values = res['values']
# 打印数组
print('columns:\n', columns)
print('values:\n', values)
# columns 中每一个元素 ---->values中的每一列的说明、解释
# (1)创建画布
plt.figure()
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘制图形
# 准备数据
x = values[-1, 6:] # 一维数据
# labels --->各部分的名称
labels = [tmp[:2] for tmp in columns[6:]]
# shadow ---> 阴影
# explode --离心半径--各部分扇形原理饼心的距离
# 也可以理解为各部分扇形之间的缝隙
explode = (0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09)
# colors --便是饼图的颜色
colors = ['#D2691E', '#DA70D6', '#8B7D6B','#D2691E', '#DA70D6', '#8B7D6B','#D2691E', '#DA70D6', '#8B7D6B']
# autopct ---各部分占比的情况
autopct = '%.2f%%'
# pctdistance ---表示显示的占比情况距离饼心的距离---默认为0.6半径
# labeldistance --表示显示各部分labels距离饼心的距离--默认为1.1半径
# radius --饼图半径--默认为1
plt.pie(x,
labels=labels,
shadow=True,
explode=explode,
colors=colors,
autopct=autopct,
pctdistance=0.6,
labeldistance=1.1,
radius=1
)
# 将椭圆的饼 ---->圆形的饼
plt.axis('equal')
# 增加标题
plt.title('2017年第一季度各个产业的增加总值占比饼图')
# 增加图例
plt.legend(labels, loc=1)
# 保存图片
plt.savefig('./2017年第一季度各个产业的增加总值占比饼图.png')
# (3)图形展示
plt.show()
案例7:(箱线图)
效果图:
# 箱线图---利用数据5个统计量来描述数据
# 5个统计量: ---最小值、下四分位数、中位数、上四分位数、最大值
# 分位数:---对数据进行升序排序,---获取对应位置的数据 ---分位数
# 利用箱线图来查看数据的对称情况、分布的离散情况
# 后续--箱线分析法---来确定异常值
# 可以使用plt.boxplot来绘制箱线图
# 以2000-2017年各季度生产增加总值为例 绘制箱线图
import numpy as np
import matplotlib.pyplot as plt
# 加载数据
res = np.load('./国民经济核算季度数据.npz')
# print(res) # <numpy.lib.npyio.NpzFile object at 0x000000000210B240>
# 遍历
# for tmp in res:
# print(tmp)
# 获取对应的数组
columns = res['columns']
values = res['values']
# 打印数组
print('columns:\n', columns)
print('values:\n', values)
# columns 中每一个元素 ---->values中的每一列的说明、解释
# (1)创建画布
plt.figure()
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘制箱线图
# 准备数据
# 需要注意:将每个箱子的数据作为一个整体
x = (values[:, 3], values[:, 4], values[:, 5])
# notch --->开缺口
# 中位数---置信区间
# sym --异常值的形状
# vert 箱子的方向,如果为True --垂直的,
# 如果为False --->水平的
# positions ---来调整箱子的位置
# widths --箱子的宽度 --两个箱子之间间距的占比
# labels ---各个箱子的名称
# meanline ---平均线
# 均线要显示,需要将 meanline置为True,也需要将showmeans也置为True
# 绘制
plt.boxplot(x,
notch=True,
sym='*',
vert=True,
# positions=[2],
widths=0.3,
labels=['第一产业', '第二产业', '第三产业'],
meanline=True,
showmeans=True
)
# 添加标题
plt.title('2000-2017年各个产业增加总值的比对箱线图')
# 增加横轴名称
plt.xlabel('产业')
# 增加纵轴名称
plt.ylabel('生产总值(亿元)')
# 保存
plt.savefig('./2000-2017年各个产业增加总值的比对箱线图.png')
# (3)图形展示
plt.show()
案例8:(k线图)
效果图:
代码实现:
# K线图---主要用于金融领域--股票走势
# 开盘价、最高价、最低价、收盘价
# 如果 开盘价 < 收盘价 ---价格在上涨---用红色柱子表示
# 如果 开盘价 > 收盘价 --- 价格在下跌---用绿色柱子表示
# 利用金融数据来绘制K线图
# 安装tushare --并指定源
# pip install tushare -i https://pypi.douban.com/simple
# 安装mpl_finance --并指定源
# pip install mpl_finance -i https://pypi.douban.com/simple
import tushare as ts
import numpy as np
import matplotlib.pyplot as plt
import mpl_finance as mpf
# (1) 创建画布
fig = plt.figure()
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘制图形
# 准备数据 ---需要获取某支股票的交易信息数据
# 获取股票代码为 600728 的这支股票的交易信息
# 参数1 股票代码
# ktype --每一个交易日
# start ---开始日期
# end ---结束日期 ---表示到现在
# autype='qfq' --复权
data = ts.get_k_data('600728', ktype='D', start='2018-11-01', end='', autype='qfq')
print('data:\n', data)
print('*' * 100)
# 筛选出 ohlc数据
# 把每一列的列名 --->列表组合 --->索引
prices = data[['open', 'high', 'low', 'close']]
print('prices:\n', prices)
print('*' * 100)
# 筛选日期数据
# dates = data['date']
# print('dates:\n', dates)
# print('*' * 100)
# 合并数据
# candledata = np.column_stack((list(range(len(dates))), prices))
# print(candledata)
# np.concatenate()
# reshape
# 获取序号 --并转成2维
id = np.arange(data.shape[0]).reshape((-1, 1))
print('id:\n', id)
print('*' * 100)
# 合并数据
# prices.values ---->ndarray
candle_data = np.concatenate((id, prices.values), axis=1)
print(candle_data)
# 获取坐标系
# 参数
# 左间距、下间距 ---图形宽度、图形高度
# [left, bottom, width, height]
ax = fig.add_axes([0.1, 0.2, 0.8, 0.6]) #
# 绘制图形
# 参数1 ax---坐标系
# 参数2 ---数据
# width ---每一个柱子的宽度
mpf.candlestick_ohlc(ax, candle_data, width=0.5, colorup='r', colordown='g')
# 增加标题
plt.title('k线图')
# 保存
plt.savefig('./k线图.png')
# (3)图形展示
plt.show()
案例9:(雷达图)
效果图:
代码实现:
# 雷达图----类似于 雷达辐射范围的图形
# 从不同方向来剖析一个对象在不同方向的评价,可以用来绘制(高维度)数据
# 如:王者战报信息
# 输出、KDA、打野、推进、生存、经济 ---->(2,3,4,3,2,1)
# 雷达图--->直接使用平面雷达图---可以用来描述高维度空间的点 --->列数超过2的数组
import matplotlib.pyplot as plt
import numpy as np
# 极坐标 ---通过p,a来描述向量,以固定长度为p的向量以中心为轴旋转a弧度到达指定向量位置。
# 如果旋转一圈,将与原始位置重合,旋转一圈的角度为 2*pi弧度
# 如何绘制雷达图?
# (1)创建画布
plt.figure()
# 修改参数,让其支持中文
plt.rcParams['font.sans-serif'] = 'SimHei'
# 修改参数让其重新支持负号
plt.rcParams['axes.unicode_minus'] = False
# (2)绘图
# 准备数据
# 绘制雷达图
# 角度
# 将 2* pi弧度划分为属性个扇形
datalength = 5
# 角度节点
# 将 2* pi 划分为 5个扇形范围
# 创建等差数组
# 不包含尾节点
angle = np.linspace(0, 2 * np.pi, datalength, endpoint=False)
print(angle)
# 闭合角度
angle = np.concatenate((angle, [angle[0]]), axis=0)
print('闭合之后的角度:\n', angle)
# # 数据
data = np.array([2, 3.5, 4, 4.5, 5])
print(data)
# 闭合数据 [data[0]]=数组的第一个元素,因此变成了闭合
data = np.concatenate((data, [data[0]]), axis=0)
print('闭合之后的数据:\n', data)
# #
plt.polar(angle, data, color='r', marker='*', markersize=15)
#
# 构建刻度
xticks = ['生存评分', '输出评分', '团战评分', 'KDA', '发育评分']
# 修改刻度
plt.xticks(angle, xticks)
# 标题
plt.title('该玩家的王者战报信息雷达图')
# 保存
plt.savefig('./该玩家的王者战报信息雷达图.png')
# # (3)图形展示
plt.show()
# 折线图、散点图、柱状图、直方图、饼图、箱线图、K线图、雷达图
# 了解更多:https://matplotlib.org/gallery/index.html