优秀的编程知识分享平台

网站首页 > 技术文章 正文

按组绘制多子图(多子图绘图)

nanyue 2024-10-14 11:31:55 技术文章 8 ℃

1. Python绘制Origin画廊中的这个图:http://blog.originlab.com/plot-multi-panel-graphs-by-group。

2. 代码如下,也可从这个链接中下载:https://gitee.com/xiaoliulaolai/analyze_visualize。

#!/usr/bin/env python
# coding=utf-8

import os
import numpy as np
import matplotlib.pyplot as plt


'''
图及数据来源:http://blog.originlab.com/plot-multi-panel-graphs-by-group
代码:https://gitee.com/xiaoliulaolai/analyze_visualize
'''


'''
创建图形,包括2x2布局的四个子图
返回:图形及四个子图
'''
def create_figure():
    fig = plt.figure()  # 创建图形
    ax1 = plt.subplot(221)  # 图形分成2x2的网格,每个网格一个子图,取第1个子图(左上)
    ax2 = plt.subplot(222)  # 取第2个子图(右上)
    ax3 = plt.subplot(223)  # 取第3个子图(左下)
    ax4 = plt.subplot(224)  # 取第4个子图(右下)
    for ax in (ax1, ax2, ax3, ax4):  # 对每个子图
        for pos in ('top', 'right'):  # 每个子图的上边框和右边框
            ax.spines[pos].set_visible(False)  # 隐藏每个子图的上边框和右边框
    plt.subplots_adjust(left=0.1, bottom=0.13, right=0.95, top=0.9, hspace=0.3, wspace=0.3)  # 调整图形左下右上的边距,垂直间距,水平间距
    return (fig, ax1, ax2, ax3, ax4)  # 返回图形及四个子图
    
    
'''
在传入的子图中绘画两个点线图
参数:
ax: 传入的子图
xTime: X轴数据
yCity: 第一个点线图的Y数据
yCountry: 第二个点线图的Y数据
treatmentData: 用于分组的数据
treatment: 绘画在子图的数据所在组
yLimit: Y轴的刻度范围
yLabel: Y轴主刻度的位置
yMinor: Y轴次刻度的位置
'''
def plot_line_scatter(ax, xTime, yCity, yCountry, treatmentData, treatment, yLimit, yMajor, yMinor):
    x = xTime[treatmentData == treatment]  # 从X轴的数据中取出给定组的数据
    y1 = yCity[treatmentData == treatment]  # 从第一个Y数据中取出给定组的数据
    y2 = yCountry[treatmentData == treatment]  # 从第二个Y数据中取出给定组的数据
    
    # 绘画点线图,点的形状为圆,分别设置颜色,点的大小,线的宽度
    ax.plot(x, y1, marker='o', color='#ef0000', markersize=5, linewidth=0.5)
    ax.plot(x, y2, marker='o', color='#336699', markersize=5, linewidth=0.5)
    
    ax.set_xlabel('Time (ms)')  # 设置X轴标签
    ax.set_ylabel(treatment)  # 设置Y轴标签
    ax.set_xlim(100, 200)  # 设置X轴刻度范围
    ax.set_xticks(np.linspace(110, 190, 5), minor=True)  # 设置X轴次刻度位置
    ax.set_ylim(yLimit)  # 设置Y轴刻度范围
    ax.set_yticks(yMajor)  # 设置Y轴主刻度位置
    ax.set_yticks(yMinor, minor=True)  # 设置Y轴次刻度位置
    
    
if __name__ == '__main__':
    currentFile = os.path.realpath(__file__)  # 获得当前文件的路径,即001.py这个文件的路径
    currentDir = os.path.dirname(currentFile)  # 获得当前文件所在的目录
    
    # 读取数据,数据文件为001.txt,与当前文件在同一目录下,读取的类型为float浮点型,数据分隔符为制表符(\t)
    # 头两行为非数据,跳过两行,而后两列为字符串,则只读取前四列为浮点类型,而后两列读取为字符串类型
    colsTimeCityCountryYear = np.loadtxt(fname=currentDir + os.path.sep + '001.txt', dtype=float, delimiter='\t', skiprows=2, usecols=(0, 1, 2, 3))
    colsDateTreatment = np.loadtxt(fname=currentDir + os.path.sep + '001.txt', dtype=str, delimiter='\t', skiprows=2, usecols=(4, 5))

    names = ('Time', 'City', 'Country', 'Year', 'Date', 'Treatment')  # 每列数据名
    units = ('ms', '', '', '', '', '')  # 单位
    treatments = ('untreated', 'treatment1', 'treatment2', 'treatment3')  # treament的四个组名
    
    fig, ax1, ax2, ax3, ax4 = create_figure()  # 创建图形,并得到四个子图
    
    xTime = colsTimeCityCountryYear[:, 0]  # 取出Time列
    yCity = colsTimeCityCountryYear[:, 1]  # 取出City列
    yCountry = colsTimeCityCountryYear[:, 2]  # 取出Country列
    treatmentData = colsDateTreatment[:, 1]  # 取出Treatment列
    yLimits = ((8, 34), (14, 41), (-1, 19), (14, 48))  # 定义四个子图Y轴的刻度范围
    # 分别定义四个子图Y轴的主刻度和次刻度的位置
    yMajors = (np.linspace(8, 32, num=7), np.linspace(16, 40, num=7), np.linspace(0, 16, num=5), np.linspace(16, 48, num=9))
    yMinors = (np.linspace(10, 34, num=7), np.linspace(14, 38, num=7), np.linspace(2, 18, num=5), np.linspace(18, 46, num=8))
    
    # 分别在四个子图中按给定的treatment对应组绘画点线图
    for (idx, ax) in enumerate([ax1, ax2, ax3, ax4]):
        plot_line_scatter(ax, xTime, yCity, yCountry, treatmentData, treatments[idx], yLimits[idx], yMajors[idx], yMinors[idx])
    
    # 设置整个图形的图例,显示在图形中间的顶头位置,两个点线图的图例显示成一行(即两列),不显示边框
    plt.figlegend([names[1], names[2]], loc='upper center', ncol=2, frameon=False)  #, prop=matplotlib.font_manager.FontProperties(weight='bold'))
    plt.show()  # 显示图形

3. 绘制结果图:

4. 技术要点:导入数据的技巧;创建图形时布局多个子图;调整图形的边距;子图边框的隐藏;布尔值对数据的提取;点线图的绘制与相关设置;坐标的范围、标签、主次刻度等的设置;整图的图例创建及设置。

Tags:

最近发表
标签列表