Python数据可视化(5):子图的绘制及坐标轴的共享

5.1 subplot()函数

pyplot的subplot()函数可以在规划好的某个区域中绘制单个子图,subplot()函数的语法格式下。

subplot(nrows,ncols,index,projection,polar,sharex,sharey,label,**keargs)

nrows,ncols:表示规划区域的行数和列数

index:表示选择区域的索引,从1开始

projection:子图投影的类型

5.1.1 绘制单子图

import matplotlib.pyplot as plt
ax_one=plt.subplot(326)  #分成3行2列,在6的位置画图,注意索引从1开始
ax_one.plot([1,2,3,4,5])
ax_two=plt.subplot(312)
ax_two.plot([1,2,3,4,5])
plt.title('41')
plt.show()

5.1.2 实例1 :某工厂产品A和产品B去年的销售额分析

要点:1、在绘制的点的上方写下注释!!!

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ["SimHei"]
x = [x for x in range(1, 13)]
y1 = [20, 28, 23, 16, 29, 36, 39, 33, 31, 19, 21, 25]
y2 = [17, 22, 39, 26, 35, 23, 25, 27, 29, 38, 28, 20]
labels = ['1 月', '2 月', '3 月', '4 月', '5 月', '6 月', '7月', '8 月', '9 月', '10 月', '11 月', '12 月']
ax1 = plt.subplot(211)
ax1.plot(x, y1, 'm--o', lw=2, ms=5, label='产品A')
ax1.plot(x, y2, 'g--o', lw=2, ms=5, label='产品B')
ax1.set_title("产品A 与产品B的销售额  41", fontsize=11)
ax1.set_ylim(10, 45)
ax1.set_ylabel('销售额(亿元)')
ax1.set_xlabel('月份')
for xy1 in zip(x, y1):#text()会将文本放置在轴域的任意位置。 文本的一个常见用例是标注绘图的某些特征,而annotate()方法提供辅助函数,使标注变得容易
    ax1.annotate("%s" % xy1[1], xy=xy1, xytext=(-5, 5), textcoords='offset points')
#"%s" % xy1[1]输出字符串!
for xy2 in zip(x, y2):
    ax1.annotate("%s" % xy2[1], xy=xy2, xytext=(-5, 5), textcoords='offset points')
ax1.legend()
ax2 = plt.subplot(223)
ax2.pie(y1, radius=1, wedgeprops={'width':0.5}, labels=labels, autopct='%3.1f%%', pctdistance=0.75)
ax2.set_title('产品A的销售额 ')
ax3 = plt.subplot(224)
ax3.pie(y2, radius=1, wedgeprops={'width':0.5}, labels=labels,autopct='%3.1f%%', pctdistance=0.75)
ax3.set_title('产品B的销售额 ')
plt.tight_layout()
plt.show()

运行结果:

 5.1.3 绘制多子图

使用pyplot的subplots()函数可以在规划好的所用区域中一次绘制多个子图,subplots()函数语法格式如下:

subplots(nrows=1,ncols=1,sharex=False,sharey=False,squeeze=True,subplot_kw=None,gridspec_kw=None,**fig_kw)

sharex,sharey:表示是否共享子图的x轴和y轴

squeeze:表示是否返回压缩的Axes对象,当为True时,subplots()会返回一个axes对象

这个axes对象的形式是:矩阵(列表的形式!)

[[<Axes: > <Axes: > <Axes: >]
 [<Axes: > <Axes: > <Axes: >]]

(注意使用过程中,行和列的索引从0开始!!!)

import matplotlib.pyplot as plt
fig, ax_arr = plt.subplots(2, 2)
ax_thr = ax_arr[1, 0]  #获取1行0列!!!
ax_thr.plot([1, 2, 3, 4, 5])
plt.title('41')

5.1.4 实例2:部分国家养猫人群比例与养狗人群比例分析 

要点:1、 """ 在每个矩形条的右边附加一个文本标签, 以显示其高度"""

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ["SimHei"]

def autolabel(ax, rects):
    """ 在每个矩形条的上方附加一个文本标签, 以显示其高度"""
    for rect in rects:
        width = rect.get_width()   
        ax.text(width  + 3, rect.get_y() , s='{}'.format(width), ha='center', va='bottom')
y = np.arange(12)
x1 = np.array([19, 33, 28, 29, 14, 24, 57, 6, 26, 15, 27, 39])
x2 = np.array([25, 33, 58, 39, 15, 64, 29, 23, 22, 11, 27, 50])
labels = np.array(['中国', '加拿大', '巴西', '澳大利亚', '日本', '墨西哥', 
                   '俄罗斯', '韩国', '瑞士', '土耳其', '英国', '美国'])
fig, (ax1, ax2) = plt.subplots(1, 2)
barh1_rects = ax1.barh(y, x1, height=0.5, tick_label=labels, color='#FFA500')
ax1.set_xlabel('人群比例(%)')
ax1.set_title('部分国家养猫人群的比例 41')
ax1.set_xlim(0, x1.max() + 10)
autolabel(ax1, barh1_rects)
barh2_rects = ax2.barh(y, x2, height=0.5, tick_label=labels, color='#20B2AA')
ax2.set_xlabel('人群比例(%)')
ax2.set_title('部分国家养狗人群的比例 41')
ax2.set_xlim(0, x2.max() + 10)
autolabel(ax2, barh2_rects)
plt.tight_layout()
plt.show()

5.2 绘制自定义区域的子图

其实可以使用subplot()绘制单个子图进行设置

subplot2grid(shape,loc,rowspan=1,fig=None,**kwargs)

 shape:图的结构,分成几行几列

loc:要绘制的图像的位置,行和列索引从0开始!  图像从哪里开始!

rowspan:表示向下跨越的列数,默认为1(即不跨越)

colspan:表示向右跨越的行数,默认为1(即不跨越)

import matplotlib.pyplot as plt
ax1 = plt.subplot2grid((2, 3), (0, 2))
ax1.plot([1, 2, 3, 4, 5])
ax2 = plt.subplot2grid((2, 3), (1, 1), colspan=2)  #向右跨越1个单位!!!则这个图在第1行的第1到2列画图!!!!!
ax2.plot([1, 2, 3, 4, 5])
plt.title('41')
plt.show()

 5.2.2 实例3:2017年和2018年抖音用户分析

要点:1、添加无指向性文本!(在柱形图或者条形图的顶端写上数字)

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
data_2017 = np.array([21, 35, 22, 19, 3])
data_2018 = np.array([13, 32, 27, 27, 1])
x = np.arange(5)
y = np.array([51, 73, 99, 132, 45])
labels = np.array(['一线城市', '二线城市', '三线城市', '四线及以外', '其他国家及地区'])
average = 75
bar_width = 0.5
def autolabel(ax, rects):
    """ 在每个矩形条的上方附加一个文本标签, 以显示其高度"""
    for rect in rects:
        height = rect.get_height()     
        ax.text(rect.get_x()  + bar_width/2, height + 3, s='{}'.format(height), ha='center', va='bottom')
ax_one = plt.subplot2grid((3,2), (0,0), rowspan=2, colspan=2)
bar_rects = ax_one.bar(x, y, tick_label=labels, color='#20B2AA', width=bar_width)
ax_one.set_title('抖音2018vs2017人群增长倍数  41')
ax_one.set_ylabel('增长倍数')
autolabel(ax_one, bar_rects)
ax_one.set_ylim(0, y.max() + 20)
ax_one.axhline(y=75, linestyle='--', linewidth=1, color='gray')
ax_two = plt.subplot2grid((3,2), (2,0))
ax_two.pie(data_2017, radius=1.5, labels=labels, autopct='%3.1f %%', 
           colors=['#2F4F4F', '#FF0000', '#A9A9A9', '#FFD700', '#B0C4DE'])
ax_two.set_title('2017年抖音用户地区分布的比例')
ax_thr = plt.subplot2grid((3,2), (2,1))
ax_thr.pie(data_2018, radius=1.5, labels=labels, autopct='%3.1f %%', 
           colors=['#2F4F4F', '#FF0000', '#A9A9A9', '#FFD700', '#B0C4DE' ])
ax_thr.set_title('2018年抖音用户地区分布的比例')
plt.tight_layout()
plt.show()

5.3 共享子图的坐标轴

5.3.1 共享相邻子图的坐标轴

在同一画布中,若子图与其他子图的同方向的坐标轴相同,则可以共享子图之间同方向的坐标轴
共享相邻子图的坐标轴:

使用pyplot的subplots()函数绘制子图时,

可以通过sharex或sharey参数控制是否共享x轴或y轴。sharex或sharey参数支持False或‘none’、True或’all’、‘row’、‘col’中任一取值

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['axes.unicode_minus'] = False
x1 = np.linspace(0, 2 *np.pi, 400)
x2 = np.linspace(0.01, 10, 100)
x3 = np.random.rand(10)
x4 = np.arange(0,6,0.5)
y1 = np.cos(x1 ** 2)
y2 = np.sin(x2)
y3 = np.linspace(0,3,10)
y4 = np.power(x4,3)
fig, ax_arr = plt.subplots(2, 2, sharex=True)
ax1 = ax_arr[0, 0]
ax1.plot(x1, y1)
ax2 = ax_arr[0, 1]
ax2.plot(x2, y2)
ax3 = ax_arr[1, 0]
ax3.scatter(x3, y3)
ax4 = ax_arr[1, 1]
ax4.scatter(x4, y4)
plt.title('41')
plt.show()

 5.3.2 共享非相邻子图的坐标轴

当使用subplot()函数绘制子图时,也可以将代替其他子图的变量赋值给shares或sharey参数,此时可以共享非相邻子图之间的坐标轴。

示例:

import numpy as np
x1 = np.linspace(0,2*np.pi,400)
y1 = np.cos(x1**2)
x2 = np.linspace(0.01,10,100)
y2 = np.sin(x2)
ax_one = plt.subplot(221)
ax_one.plot(x1,y1)
ax_two = plt.subplot(224, sharex = ax_one)
ax_two.plot(x2,y2)

5.3.3 实例4 :某地区全年平均气温与降水量蒸发量的关系

# 实例9某地区全年平均气温降水量、蒸发量的关系
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
month_x = np.arange(1, 13, 1)
# 平均气温
data_tem = np.array([2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 
                     20.3, 33.4, 23.0, 16.5, 12.0, 6.2])
# 降水量
data_precipitation = np.array([2.6, 5.9, 9.0, 26.4, 28.7, 70.7,  
                               175.6, 182.2, 48.7, 18.8, 6.0, 2.3])
# 蒸发量
data_evaporation = np.array([2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 
                             135.6, 162.2, 32.6, 20.0, 6.4, 3.3])
fig, ax = plt.subplots()
bar_ev = ax.bar(month_x, data_evaporation, color='orange', tick_label=['1月', '2月', '3月', '4月', '5月', '6月',
                                                                       '7月', '8月', '9月', '10月', '11月', '12月'])
bar_pre = ax.bar(month_x, data_precipitation, bottom=data_evaporation, color='green')
ax.set_ylabel('水量 (ml)')
ax.set_title('平均气温与降水量、蒸发量的关系 2020080603052')
ax_right = ax.twinx()
line = ax_right.plot(month_x, data_tem, 'o-m')
ax_right.set_ylabel('气温($^\circ$C)')
# 添加图例
plt.legend([bar_ev, bar_pre, line[0]], ['蒸发量', '降水量', '平均气温'],
           shadow=True, fancybox=True)
plt.show()

5.4 子图的布局

当带有标题的多个子图并排显示时,多个子图会因为区过于紧凑而出现标题和坐标轴之间相互重叠的问题,而且子图元素的摆放过于紧凑时,也影响用户的正常查看。matplotlib中提供一些调整子图的方法,包括约束布局,紧密布局,自定义布局,通过这些方法来合理布局多个子图。

5.4.1 约束布局

(1)使用constrined_layout参数

fig, axs = plt.subplots(2, 2, constrained_layout=True)

(2)修改figure.constrained_layout.use配置项

plt.rcParams['figure.constrained_layout.use'] = True

5.4.2 紧密布局

紧密布局和约束布局相似,采用紧凑的方法将子图排列到画布中,仅适用于刻度标签、坐标轴标签和标题位置的调整

(1)调用tight_layout()函数

(2)修改配置项

5.4.3 自定义布局

(1)使用GridSpec方法创建子图的布局结构

(2)使用add_gridspec()方法向画布中田间布局结构

实例:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
plt.rcParams["font.sans-serif"] = ["SimHei"]
x_month = np.array(['1月', '2月', '3月', '4月', '5月', '6月'])
y_sales = np.array([2150, 1050, 1560, 1480, 1530, 1490])
x_citys = np.array(['北京', '上海', '广州', '深圳', '浙江', '山东'])
y_sale_count = np.array([83775, 62860, 59176, 64205, 48671, 39968])
fig = plt.figure(constrained_layout=True)
gs = fig.add_gridspec(2, 2)
ax_one = fig.add_subplot(gs[0, :])
ax_two = fig.add_subplot(gs[1, 0])
ax_thr = fig.add_subplot(gs[1, 1])
ax_one.bar(x_month, y_sales, width=0.5, color='#3299CC')
ax_one.set_title('2018年上半年某品牌汽车的销售额  41')
ax_one.set_ylabel('销售额(亿元)')
ax_two.plot(x_citys, y_sale_count, 'm--o', ms=8)
ax_two.set_title('分公司某品牌汽车的销量')
ax_two.set_ylabel('销量(辆)')
ax_thr.stackplot(x_citys, y_sale_count, color='#9999FF')
ax_thr.set_title('分公司某品牌汽车的销量')
ax_thr.set_ylabel('销量(辆)')
plt.show()

  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来回答你的问题。 在 Python 中,我们可以使用 PyQtGraph 库来进行数据可视化。要自定义坐标轴信息,我们可以使用 Qt 的 QGraphicsScene 和 QGraphicsView 类来创建一个自定义的图形场景,并在其中添加自定义的坐标轴。 下面是一个简单的示例代码,演示如何绘制一个带有自定义坐标轴信息的图形: ```python import pyqtgraph as pg from PyQt5.QtCore import Qt from PyQt5.QtGui import QPen from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView class CustomAxis(pg.AxisItem): def __init__(self, orientation): super().__init__(orientation) def tickStrings(self, values, scale, spacing): return ["{:.2f}".format(value) for value in values] class CustomView(QGraphicsView): def __init__(self, scene): super().__init__(scene) self.setRenderHint(QPainter.Antialiasing) # 设置坐标轴范围和标签 self.plotItem = pg.PlotItem() self.plotItem.setLabel('left', 'Y Axis', units='V') self.plotItem.setLabel('bottom', 'X Axis', units='s') self.plotItem.showGrid(x=True, y=True) # 创建自定义坐标轴 self.axis = CustomAxis('bottom') self.plotItem.axes['bottom']['item'] = self.axis self.plotItem.layout.addItem(self.axis, 2, 1) self.setSceneRect(0, 0, 800, 600) self.setScene(scene) def resizeEvent(self, event): super().resizeEvent(event) self.fitInView(self.sceneRect(), Qt.KeepAspectRatio) if __name__ == '__main__': app = QApplication([]) scene = QGraphicsScene() view = CustomView(scene) # 添加数据 data = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] pen = QPen(Qt.red) plot = pg.PlotCurveItem(data=data, pen=pen) view.plotItem.addItem(plot) view.show() app.exec_() ``` 在这个示例中,我们创建了一个 `CustomAxis` 类,它继承了 PyQtGraph 中的 `AxisItem` 类,并覆盖了 `tickStrings()` 方法,以便自定义坐标轴标签的格式。然后,我们创建了一个 `CustomView` 类,它继承了 Qt 中的 `QGraphicsView` 类,并在其中创建了一个自定义的图形场景和一个自定义的坐标轴。最后,我们创建了一个数据点列表,并使用 `PlotCurveItem` 类将数据绘制到图形场景中。 希望这个示例能够帮助你实现自定义坐标轴信息。如果你有任何问题,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值