from matplotlib import patches
采用patches.Rectangle()绘制长方形
获得了长方形对象后,使用对画布添加对象的命令add_artist(),将矩形添加到我们的图像中;
例子:画有序条形图
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline from matplotlib import patches # step1 : 导入数据 df_raw = pd.read_excel("C:\\Users\\30565\\Documents\\Python Scripts\\data-visualization-50\\mpg_ggplot2.xlsx") df_raw.head()
df = df_raw[['cty','manufacturer']].groupby("manufacturer").apply(lambda x:x.mean()) df
df.sort_values('cty',inplace=True) #排序 df.reset_index(inplace=True) #修正索引 # step2: 绘制有序条形图 fig,ax = plt.subplots(figsize=(16,10)) #往后均是对ax坐标系操作 # 绘制柱状图 ax.vlines(x=df.index #横坐标 ,ymin=0 # 柱状图在y轴的起点 ,ymax = df.cty # 柱状图在y轴的终点 ,color = 'firebrick' # 柱状图的颜色 ,alpha = 0.7 # 柱状图的透明度 ,linewidth = 20) # 柱状图的线宽 # step3:添加文本 # enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标, for i, cty, in enumerate(df.cty): ax.text(i, # 文本的横坐标位置 cty+0.5, # 文本的纵坐标位置 round(cty, 1), # 对文本中数据保留一位小数 horizontalalignment = 'center') # 相对于xy轴,水平对齐 # step4:添加补丁
# 添加绿色的补丁 p1 = patches.Rectangle((0.57, -0.005), # 矩形左下角坐标 width = 0.335, # 矩形的宽度 height = 0.13, # 矩形的高度 alpha = 0.1, # 矩阵的透明度 facecolor = 'green' # 是否填充矩阵(设置为绿色) ) # 保持矩形显示在图像最上方 # 添加红色的补丁 p2 = patches.Rectangle((0.124, -0.005), # 矩形左下角坐标 width = 0.446, # 矩形的宽度 height = 0.13, # 矩形的高度 alpha = 0.1, # 矩阵的透明度 facecolor = 'red' # 是否填充矩阵(设置为红色) ) # 保持矩形显示在图像最上方 # 将补丁添加至画布 fig.add_artist(p1) # 获取子图,并且将补丁添加至子图 fig.add_artist(p2) # 获取子图,并且将补丁添加至子图 # step5:装饰 ax.set(ylabel='Miles Per Gallon',ylim=(0, 30)) # 横坐标的刻度标尺 plt.xticks(df.index, # 横坐标的刻度位置 df.manufacturer.str.upper(), # 刻度标尺的内容(先转化为字符串,再转换为大写) rotation = 60, # 旋转角度 horizontalalignment = 'right', # 相对于刻度标尺右移 fontsize = 12) # 字体尺寸 plt.title('Bar Chart for Highway Mileage', # 子图标题名称 fontdict = {'size': 22}) # 标题字体尺寸 plt.show() # 显示图像
观察 patches.Rectangle((x,y),width,height)参数
发现其中的x,y和坐标轴中的x,y是不一致的,也就是我们建立的坐标轴是没用的!
我们发现,x,y,width,height均是小于1的数据,通过测试发现,其实整个画布的左下角坐标是(0,0),width=1,height=1
如
问题1 :请使用Rectangle和add_artist,画出NASSAN和TOYOTA柱子之间,和NASSAN一样高的长方形
p0 = patches.Rectangle((0.62, 0.127), # 矩形左下角坐标 width = 0.037, # 矩形的宽度 height = 0.453, # 矩形的高度 alpha = 0.1, # 矩阵的透明度 facecolor = 'blue' # 是否填充矩阵(设置为绿色) ) # 保持矩形显示在图像最上方
问题2: 之前学过add_patch(),那么这里可以用add_patch()替换?
p1 = patches.Rectangle((-2.0, -1), # 补丁左下角的坐标 width = .3, # 补丁的宽度 height = 3, # 补丁的高度 alpha = .2, # 补丁的透明度 facecolor = 'red') # 补丁内部的颜色 p2 = patches.Rectangle((1.5, 27), # 补丁左下角的坐标 width = .8, # 补丁的宽度 height = 5, # 补丁的高度 alpha = .2, # 补丁的透明度 facecolor = 'green') # 补丁内部的颜色 plt.gca().add_patch(p1) # 获取子图,并且将补丁添加至子图 plt.gca().add_patch(p2) # 获取子图,并且将补丁添加至子图
这里也遇到过:
def encircle(x, y, ax=None, **kw): if not ax: ax = plt.gca() # 如果没有子图对象,那么就创建一个新的子图对象 # np.c_中的c是column(列)的缩写,是按列叠加两个矩阵的意思,也可以说是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等,类似于pandas中的merge()。 p = np.c_[x, y] hull = ConvexHull(p) # 将数据集输入到ConverHull中,自动生成凸包类型的对象(hull) ploy = plt.Polygon(p[hull.vertices, :], **kw) # 利用plt.Polygon绘制多边形 ax.add_patch(ploy) # 将多边形ploy修补到当前子图中
无论是plt.gca().add_patch()或者是ax.add_patch()操作对象均是ax,也就是坐标轴内的范围和标题/坐标轴的名称这些字,但是不包括名称后面的画布
因此ax.add_patch()只能对坐标轴内的范围有效,因此我们相对轴外的范围(画布的领域)进行操作,需要对fig操作!
而fig上是没有add_patch()这个方法的,因此只能采用add_artist(),如
fig.add_patch(p0)
相对的,ax上却可以使用add_artist(),其功能和add_patch()一样,知识在轴内显示图像,如
p1 = patches.Rectangle((-2.0, -1), # 补丁左下角的坐标 width = .3, # 补丁的宽度 height = 3, # 补丁的高度 alpha = .2, # 补丁的透明度 facecolor = 'red') # 补丁内部的颜色 p2 = patches.Rectangle((1.5, 27), # 补丁左下角的坐标 width = .8, # 补丁的宽度 height = 5, # 补丁的高度 alpha = .2, # 补丁的透明度 facecolor = 'green') # 补丁内部的颜色 # plt.gca().add_patch(p1) # 获取子图,并且将补丁添加至子图 # plt.gca().add_patch(p2) # 获取子图,并且将补丁添加至子图 plt.gca().add_artist(p1) plt.gca().add_artist(p2)
依然可以获得正确的结果;