【Python】机器学习绘图神器Matplotlib首秀!
公众号:尤而小屋
作者:Peter
编辑:Peter
Matplotlib是一个非常经典的绘图库,甚至有人将numpy+pandas+matplotlib
称之为数据分析三剑客,足以说明这个库的重要性。虽然Peter钟情于Plotly,但掌握Matplotlib绘制技巧也非常重要。
基于Matplotlib的绘图技巧太多了,想深入学习的小伙伴建议直接官网:https://matplotlib.org/
从本文中你将学习到以下几点:
基本图形绘制:折线图、柱状图、直方图、双轴线图等 绘制小技巧:添加图例、标题、注释、颜色等 实战:股票趋势图和K线图制作
![](https://filescdn.proginn.com/be9e0bb54f1628db067147c5f9bb3e77/7365bf4ecac695ed3d57e417e4c5c73d.webp)
导入库
一般绘图的时候需要导入常见的库;在使用matplotlib绘制的时候还需要解决中文的问题
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决负号“-”显示为
plt.rcParams['axes.unicode_minus'] = False
折线图
x = [2,3,4]
y = [4,6,8]
plt.plot(x,y)
plt.show()
![](https://filescdn.proginn.com/42e5537d103aff44d1c5fac7a9f47a7f/40e86cbd8512ea9dbcd85e2f2cce743e.webp)
多折线图
# 默认参数
x1 = np.array([1,3,5])
y1 = x1 + 4
plt.plot(x1,y1)
# 第二条红线
y2 = x1 * 2
plt.plot(x1,y2,color="red",linewidth=3,linestyle="--")
plt.show()
![](https://filescdn.proginn.com/0863ba864a55991583fb8a8f846491ae/470f33776d51d98c551bc762f1cef571.webp)
柱状图
x = [2,3,4,5,6]
y = [4,6,8,10,12]
plt.bar(x,y)
plt.show()
![](https://filescdn.proginn.com/23a637f4d945b440e566497d2e4cf692/558a49e21d3da897ca6a759b41e3cd95.webp)
散点图
x = np.random.rand(20) # 0-1之间的20个随机数
y = np.random.rand(20)
plt.scatter(x,y)
plt.show()
![](https://filescdn.proginn.com/f333b719fe4688035ba4f3795cec1d47/4bcdfbedbafc0d8fd5d14cec14ee520f.webp)
直方图
# 随机生成1000个服从正态分布的数据,均值为0,标准差为1
data = np.random.randn(1000)
plt.hist(data, bins=40, edgecolor="black")
plt.show()
![](https://filescdn.proginn.com/0987771d3ba4e2380dc65e06eae4e3d9/9dc58477f313612200e3675cb97d3d53.webp)
频率直方图
主要是y轴发生了变化,全部是小数表示的
data = np.random.randn(1000)
# 区别:加上参数density=1
plt.hist(data, bins=40, density=1, edgecolor="black")
plt.show()
![](https://filescdn.proginn.com/ffceb13f827259b0b1768a1b6c54993d/7e7a593615368271bb92a4404d57136c.webp)
绘图技巧
技巧1:设置大小
x = [2,3,4]
y = [4,6,8]
plt.plot(x,y)
#设置大小 8代表800像素
plt.rcParams["figure.figsize"] = (8,6)
plt.show()
![](https://filescdn.proginn.com/42e5537d103aff44d1c5fac7a9f47a7f/40e86cbd8512ea9dbcd85e2f2cce743e.webp)
添加文字说明
文字说明包含标题、轴标签等
x = [2,3,4]
y = [4,6,8]
plt.plot(x,y)
# 添加标题和轴名称
plt.title("Title")
plt.xlabel("x axis")
plt.ylabel("y axis")
plt.show()
![](https://filescdn.proginn.com/e8df888ef791ea9f87a0a4d612582be3/094b4c5494c8adb2ef92613e1e142584.webp)
修改线条样式
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x=np.arange(1,8)
plt.plot(x,marker='>')
plt.plot(x+4,marker='+')
plt.plot(x*2,marker='o')
plt.show()
![](https://filescdn.proginn.com/036ec5c2ae466f9ccfefed06b82da70a/ee2c96e78f1648ff567fbe62636e00ae.webp)
添加注释
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False
x=[1, 2, 3, 4]
y=[1, 4, 9, 16]
plt.plot(x,y)
plt.xlabel('x坐标轴')
plt.ylabel('y坐标轴')
plt.title('标题')
# 添加注释
plt.annotate('我是注释',
xy=(2,5),
xytext=(2, 10),
arrowprops=dict(facecolor='black',
shrink=0.01),
)
plt.show()
![](https://filescdn.proginn.com/0cf6f49ec6397de58f47d9add40ce53b/3287b609621e7da3f472e2eabe8720b6.webp)
添加图例
# 第一条
x1 = np.array([1,3,5])
y1 = x1 + 4
plt.plot(x1,y1,label="y=x+4 ")
# 第二条红线
y2 = x1 * 2
plt.plot(x1,y2,
color="red",
linewidth=3,
linestyle="--",
label="y=x*2")
# 设定位置
plt.legend(loc='upper left')
plt.show()
![](https://filescdn.proginn.com/6f52855686a14fc864046f93c04cb27c/ca196f4985d3faa3504b5426dbffdbf7.webp)
调整颜色
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x=np.arange(1,8)
#颜色的多种写法
plt.plot(x,color='r') # r表示red g表示green b表示blue
plt.plot(x+1,color='0.5')
plt.plot(x+2,color='#AF00FF')
plt.plot(x+3,color=(0.1,0.2,0.3))
plt.show()
![](https://filescdn.proginn.com/6bd9807852dd88db13368052e166a5ea/436dba139fc895960305b453bec9a967.webp)
设置双轴
# 1
x1 = np.array([1,3,5])
y1 = 50*x1 + 14
plt.plot(x1,y1,label="y=50 * x + 4 ")
plt.legend(loc='upper right') # 图例位置
# 重要代码:设置双轴
plt.twinx()
# 2
y2 = -x1 * 20 + 3
plt.plot(x1,y2,color="red",
linewidth=3,
linestyle="--",
label="y=-x * 20 + 3")
plt.legend(loc='upper left')
plt.show()
![](https://filescdn.proginn.com/d4f2b53294d1e6ebfee10eab878fa3a3/99513ee1e3d1d3fb28f4f5e9e9eec120.webp)
旋转轴刻度
当某个轴的刻度值过长的时候,我们可以通过旋转的方式进行显示
x = ["Monday","Thursday","Wednesday"]
y = [4,6,8]
plt.plot(x,y)
plt.xticks(rotation=45)
plt.show()
![](https://filescdn.proginn.com/3947ecbda35e98d173254c26aa8ef20e/c6ed49612f03d261dedd48a077b2a3b5.webp)
绘制多图-方法1
import matplotlib.pyplot as plt
# 绘制第1张子图:折线图
ax1 = plt.subplot(221)
plt.plot([1, 2, 3], [2, 4, 6])
# 绘制第2张子图:柱形图
ax2 = plt.subplot(222)
plt.bar([1, 2, 3], [2, 4, 6])
# 绘制第3张子图:散点图
ax3 = plt.subplot(223)
plt.scatter([1, 3, 5], [7, 9, 11])
# 绘制第4张子图:直方图
ax4 = plt.subplot(224)
plt.hist([2, 5, 2, 8, 4])
plt.show()
![](https://filescdn.proginn.com/2041f961df950933a09b9ed624a4a016/3a20befcd91538b964f4162869cc9d16.webp)
绘制多图-方法2
subplots函数主要是两个参数:nrows表示行数,ncols表示列数;同时设置大小figsize。
函数返回的是画布fig和子图合集axes
fig, axes = plt.subplots(nrows=2, ncols=2,figsize=(10,6))
# flatten表示将子图合集展开,得到每个子图
ax1,ax2,ax3,ax4 = axes.flatten()
ax1.plot([1, 2, 3], [2, 4, 6])
ax2.bar([1, 2, 3], [2, 4, 6])
ax3.scatter([1, 3, 5], [7, 9, 11])
ax4.hist([2, 5, 2, 8, 4])
plt.show()
![](https://filescdn.proginn.com/19a396fef2b8f54cf987fc2b5d551020/dab014dda4804e8d9ae897287063dcac.webp)
实战:绘制股票趋势图
我们从Tushare官网来获取股票的数据,首先安装:
pip install tushare
获取数据
import tushare as ts
df = ts.get_k_data("000001",start="2020-05-08",end="2020-08-08")
df
![](https://filescdn.proginn.com/9a638a4612c35b5d32325eefe52079bf/bdd2a80828d01a43f9da3a77e029baf0.webp)
为了方便后续的绘图,需要将日期date字段改成索引:
# 将日期设置成索引
df1 = df.set_index("date")
![](https://filescdn.proginn.com/ecd1b50b25e80f05df1d665abcade8b6/bc3e3c8c1bae7e7d566e443a906bfb8b.webp)
默认绘图
我们使用收盘价close来绘制默认的图形
fig = df1["close"].plot()
plt.show()
![](https://filescdn.proginn.com/ecd1b50b25e80f05df1d665abcade8b6/bc3e3c8c1bae7e7d566e443a906bfb8b.webp)
添加标题
# Pandas直接绘图
fig = df["close"].plot(title="PingAn")
plt.show()
![](https://filescdn.proginn.com/89da4c37cdebe06703d77d0be6220fa7/30b049964f1c6487a77216d8faf9ba9a.webp)
上面是使用Pandas内置的折线图方法来绘制,下面使用Matplobtlib来绘制:
# 使用Matplotlib绘图
# 获取数据
# import tushare as ts
# df = ts.get_k_data("000001",start="2018-08-08",end="2020-08-08")
# 调整时间
from datetime import datetime
df["date"] = df["date"].apply(lambda x:datetime.strptime(x,"%Y-%m-%d"))
# 绘制折线图
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(df["date"],df["close"])
# 标题
plt.title("PingAn")
# 旋转
plt.xticks(rotation=-45)
plt.show()
![](https://filescdn.proginn.com/3ff791063747db3dbcd20217d890d323/bae78731bc8904a439026795a6b6847e.webp)
实战进阶:绘制K线图+成交量
首先,我们了解一点基本的股票知识:股市的涨跌对K线图的影响
![](https://filescdn.proginn.com/c7d40d9fbf8681e61ab08c9363a71839/bc719eafaa9c6f08c7317f29bda26186.webp)
![](https://filescdn.proginn.com/c7c8573df5f8f43676fe3e669cf10bc3/17921fd2da515f71e620e9f27dae9275.webp)
安装库
为了绘制k线图,我们需要安装一个库:
#安装库mpl_finance
pip install mpl_finance
获取代码
df = ts.get_k_data("000001",start="2020-09-08",end="2021-03-08")
df.head()
![](https://filescdn.proginn.com/1ae260ed2f3f8cc71e6a5f9cb48d4d10/da5aa44a56b5d0002e22200e9bd9fcb3.webp)
date:日期 open:开盘价 close:收盘价 high:最高价 low:最低价 volume:成交量 code:股票代码
日期格式转化
定义一个将字符串形式的日期转成数字型的函数:
from matplotlib.pylab import date2num
import datetime
def date_to_number(dates):
number_time = []
for date in dates:
# 字符串转时间戳格式
date_time = datetime.datetime.strptime(date,"%Y-%m-%d")
# 时间戳格式转成数字格式
number_date = date2num(date_time)
number_time.append(number_date)
return number_time
下面进行的操作是取出上面数据中的values部分并转成numpy;同时调用上面的函数:
# DataFrame转成numpy数组格式
df1 = df.values
# 将二维数组的日期转成数字(使用上面的函数)
df1[:,0] = date_to_number(df1[:,0])
绘制K线图
fig, ax = plt.subplots(figsize=(15,6))
mpf.candlestick_ochl(ax, # 绘图Axes的实例,画布中的子图
df1, # 带绘图的数据
width=0.5, # K线柱形的宽度
colorup="red", # 收盘价>开盘价
colordown="green", # 收盘价<开盘价
alpha=5) # 柱子的透明度
plt.grid(True) # 显示网格线
ax.xaxis_date() # 将x轴设置成常规的日期格式
![](https://filescdn.proginn.com/f95b70eaec3a3b96b5fd33001eb5fd85/7c30093030311e344b8758fa1e5be3b6.webp)
添加均线
下面的代码是添加5日和20日的均线数据:
![](https://filescdn.proginn.com/90d2fd0f5535e57b9e78a8115fa92bba/ba01d3bf74803f8fc3550cfd40016ece.webp)
绘制均线图
fig, ax = plt.subplots(figsize=(15,6))
mpf.candlestick_ochl(ax, # 绘图Axes的实例,画布中的子图
df1, # 带绘图的数据
width=0.5, # K线柱形的宽度
colorup="red", # 收盘价>开盘价
colordown="green", # 收盘价<开盘价
alpha=5) # 柱子的透明度
# 添加均线
plt.plot(df1[:,0],df["MA5"], c="black")
plt.plot(df1[:,0],df["MA20"])
plt.grid(True) # 显示网格线
ax.xaxis_date() # 将x轴设置成常规的日期格式
# 添加标题
plt.title("PingAn")
plt.xlabel("date")
plt.ylabel("Price")
plt.show()
![](https://filescdn.proginn.com/9248d09c4dea8826abfe16f935aac595/21e4b2df2e8c84210823696cae41e4c3.webp)
添加成交量
我们将K线图放在第一个子图位置,将成交量放在第二个位置即可:
#用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
# 画布、子图、共享x轴
fig, ax = plt.subplots(2,1,sharex=True,figsize=(15,6))
ax1,ax2 = ax.flatten()
# 第一个图
mpf.candlestick_ochl(ax1, # 绘图Axes的实例,画布中的子图
df1, # 带绘图的数据
width=0.5, # K线柱形的宽度
colorup="red", # 收盘价>开盘价
colordown="green", # 收盘价<开盘价
alpha=5) # 柱子的透明度
# 添加均线
ax1.plot(df1[:,0],df["MA5"], c="black")
ax1.plot(df1[:,0],df["MA20"])
# 显示网格线
ax1.grid(True)
# 将x轴设置成常规的日期格式
ax1.xaxis_date()
# 添加标题、轴名称等
ax1.set_title("平安股价走势图")
ax1.set_xlabel("时间")
ax1.set_ylabel("价格")
# --------------------------
# 第2个子图
ax2.bar(df1[:,0],df1[:,5])
ax2.set_xlabel("时间")
ax2.set_ylabel("成交量") # 成交量
ax2.grid(True)
ax2.xaxis_date()
plt.show()
![](https://filescdn.proginn.com/4ca6d66f0a7d9c406abcfedce2b9cf78/59292538bb6db7e42eb3756d77fe55b9.webp)
往期精彩回顾 本站qq群955171419,加入微信群请扫码:
评论