使用Matplotlib绘制平行坐标系的示例详解

 更新时间:2023年07月03日 14:33:48   作者:databook  
平行坐标系,是一种含有多个垂直平行坐标轴的统计图表,这篇文章主要为大家介绍了如何使用绘制平行坐标系,需要的小伙伴可以参考一下

平行坐标系,是一种含有多个垂直平行坐标轴的统计图表。

一般的分析图表都是分析二维的数据,而平行坐标系特别适合于分析维度较多的数据。

比如,对于学生成绩,每门学科都是一个维度,且每门学科的最高分也不一样,用单一的坐标系很难展示分析结果。

平行坐标系的图大概是下面这样的:

多个Y轴代表数据不同的属性(维度),每个Y轴的刻度可以是不一样的。

1. 准备示例数据

准备一些学生各个科目的成绩数据,用来分析整体学习情况以及是否有偏科的情况。

姓名语文数学英语物理化学
学生A100120988878
学生B1051331098789
学生C80112879095
学生D9089768988
学生E10260906665

假设:

  • 语文满分 120
  • 数学满分 150
  • 英语满分 110
  • 物理满分 90
  • 化学满分100

2. 封装绘图函数

python的绘图函数库matplotlib中,默认没有提供绘制平行坐标系的接口。

但是,基于matplotlib 提供的绘图底层接口,也可以很容易封装一个绘制平行坐标系的类。

2.1. 属性封装

根据平行坐标系上的常用元素,封装的属性主要包括:

名称类型说明
titlestring 字符串标题
x_labelslist 列表每一行数据的名称,list的长度就是数据的行数
y_labelslist 列表每一个平行的Y轴的名称,list的长度就是平行的Y轴的个数
y_datalist[list] 二维列表数据行数就是x_labels的长度,数据的列数就是y_labels的长度
y_minslist 列表每个平行的Y轴的最小值
y_maxslist 列表每个平行的Y轴的最大值
class ParallelCoord:
    """
    平行坐标系
    """
    def __init__(self, title, x_labels, y_labels, y_data, y_min, y_max):
        self.title = title
        self.x_labels = x_labels
        self.y_labels = y_labels
        self.y_data = y_data
        self.y_min = y_min
        self.y_max = y_max

2.2. 绘图封装

绘图的步骤主要有:

  • 设置画布
  • 设置标题
  • 设置各个平行的Y轴
  • 设置X轴
  • 在平行坐标系中绘制曲线
  • 绘制图例
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
import numpy as np
class ParallelCoord:
    """
    平行坐标系
    """
    def __init__(self, title, x_labels, y_labels, y_data, y_mins, y_maxs):
        self.title = title
        self.x_labels = x_labels
        self.y_labels = y_labels
        self.y_data = y_data
        self.y_mins = y_mins
        self.y_maxs = y_maxs
    def draw(self):
        # 1. 设置画布
        fig, host = plt.subplots(figsize=(10, 4))
        # 2. 设置标题
        host.set_title(self.title, fontsize=18, pad=12)
        # 3. 设置各个平行的Y轴
        # 每个坐标系的上下限不一样,调整显示方式
        dys = np.array(self.y_maxs) - np.array(self.y_mins)
        zs = np.zeros_like(self.y_data)
        zs[:, 0] = self.y_data[:, 0]
        zs[:, 1:] = (self.y_data[:, 1:] - self.y_mins[1:]) / dys[1:] * dys[
            0
        ] + self.y_mins[0]
        axes = [host] + [host.twinx() for i in range(len(self.y_labels) - 1)]
        for i, ax in enumerate(axes):
            ax.set_ylim(self.y_mins[i], self.y_maxs[i])
            ax.spines["top"].set_visible(False)
            ax.spines["bottom"].set_visible(False)
            if ax != host:
                ax.spines["left"].set_visible(False)
                ax.yaxis.set_ticks_position("right")
                ax.spines["right"].set_position(("axes", i / (len(self.y_labels) - 1)))
        # 4. 设置X轴
        host.set_xlim(0, len(self.y_labels) - 1)
        host.set_xticks(range(len(self.y_labels)))
        host.set_xticklabels(self.y_labels, fontsize=14)
        host.tick_params(axis="x", which="major", pad=7)
        host.spines["right"].set_visible(False)
        host.xaxis.tick_top()
        # 5. 在平行坐标系中绘制曲线
        colors = plt.cm.Set1.colors
        legend_handles = [None for _ in self.x_labels]
        for j in range(len(self.x_labels)):
            verts = list(
                zip(
                    [
                        x
                        for x in np.linspace(
                            0,
                            len(self.y_data) - 1,
                            len(self.y_data) * 3 - 2,
                            endpoint=True,
                        )
                    ],
                    np.repeat(zs[j, :], 3)[1:-1],
                )
            )
            codes = [Path.MOVETO] + [Path.CURVE4 for _ in range(len(verts) - 1)]
            path = Path(verts, codes)
            patch = patches.PathPatch(
                path, facecolor="none", lw=2, alpha=0.7, edgecolor=colors[j]
            )
            legend_handles[j] = patch
            host.add_patch(patch)
        # 6. 绘制图例
        host.legend(
            self.x_labels,
            loc="lower center",
            bbox_to_anchor=(0.5, -0.18),
            ncol=len(self.x_labels),
            fancybox=True,
            shadow=True,
        )
        # 显示图形
        plt.tight_layout()
        plt.show()

3. 绘制效果

封装好函数之后,绘制起来就很简单了。

#根据示例数据设置变量
title = "学生各科成绩"
x_labels = ["学生A", "学生B", "学生C", "学生D", "学生E"]
y_labels = ["语文", "数学", "英语", "物理", "化学"]
y_data = np.array(
    [
        [100, 120, 98, 88, 78],
        [105, 133, 109, 87, 89],
        [80, 112, 87, 90, 95],
        [90, 89, 76, 89, 88],
        [102, 60, 90, 66, 65],
    ]
)
y_mins = [0, 0, 0, 0, 0]
y_maxs = [120, 150, 110, 90, 100]
#绘制
pc = ParallelCoord(title, x_labels, y_labels, y_data, y_mins, y_maxs)
pc.draw()

这里为了演示,只有5条数据。

从平行坐标系的图中,可以看出,大部分物理都不错,黄色的学生E,数学偏科比较严重。

有兴趣的朋友,可以把手头的数据导入这个封装好的平行坐标系类中,看看能否从数据中发现新的东西。

到此这篇关于使用Matplotlib绘制平行坐标系的示例详解的文章就介绍到这了,更多相关Matplotlib绘制平行坐标系内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python内置函数dir详解

    Python内置函数dir详解

    这篇文章主要介绍了Python内置函数dir详解,本文讲解了命令介绍、使用实例、使用dir查找module下的所有类、如何找到当前模块下的类等内容,需要的朋友可以参考下
    2015-04-04
  • python向xls写入数据(包括合并,边框,对齐,列宽)

    python向xls写入数据(包括合并,边框,对齐,列宽)

    这篇文章主要介绍了python向xls写入数据(包括合并,边框,对齐,列宽),帮助大家更好的利用python处理表格,感兴趣的朋友可以了解下
    2021-02-02
  • python如何获得list或numpy数组中最大元素对应的索引

    python如何获得list或numpy数组中最大元素对应的索引

    这篇文章主要介绍了python如何获得list或numpy数组中最大元素对应的索引,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • python matplotlib库绘制条形图练习题

    python matplotlib库绘制条形图练习题

    这篇文章主要介绍了python matplotlib库绘制条形图练习题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • Python 哨兵值模式(Sentinel Value Pattern)的具体使用

    Python 哨兵值模式(Sentinel Value Pattern)的具体使用

    本文主要介绍了Python 哨兵值模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-05-05
  • 一个小示例告诉你Python语言的优雅之处

    一个小示例告诉你Python语言的优雅之处

    本篇中, 我们展示一下一段非常小的代码, 这段代码十分吸引我们, 因为它使用十分优雅和直接的方式解决了一个常见的问题.
    2014-07-07
  • python3利用Dlib19.7实现人脸68个特征点标定

    python3利用Dlib19.7实现人脸68个特征点标定

    这篇文章主要为大家详细介绍了python3利用Dlib19.7实现人脸68个特征点标定,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Python中实现高效的列表过滤多种方法示例

    Python中实现高效的列表过滤多种方法示例

    这篇文章主要给大家介绍了关于Python中实现高效的列表过滤的多种方法,包括基础的for循环、列表推导式、filter函数、itertools模块,以及高级的pandas和numpy库,我们还讨论了生成器的使用,以及在实际场景中的应用,需要的朋友可以参考下
    2024-12-12
  • 5款非常棒的Python工具

    5款非常棒的Python工具

    这篇文章主要为大家详细介绍了5款非常棒的Python工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Flask模板引擎之Jinja2语法介绍

    Flask模板引擎之Jinja2语法介绍

    这篇文章主要介绍了Flask模板引擎之Jinja2语法介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06

最新评论