【数据可视化】动手用matplotlib绘制关联规则网络图

下载文中数据、代码、绘图结果

文章目录

关于数据

如果想知道本文的关联规则数据是怎么来的,请阅读这篇文章

绘图函数

Python中似乎没有很方便的绘制网络图的函数。

下面是本人自行实现的绘图函数,如果想要运行,请点击上文的链接,下载数据和代码。

传入一个关联规则数据的DataFrame,这个DataFrame应该包含三列数据:antecedents,consequents,confidence,分别代表前件,后件,置信度。

py 复制代码
def plot_rules_net(rules: pd.DataFrame):
    import matplotlib.patches as patches

    # 假设你有一个包含所有药材的列表
    items = list(
        set([item for sublist in rules['antecedents'].tolist() + rules['consequents'].tolist() for item in sublist]))

    # 计算药材数量,确定顶点数
    n_items = len(items)

    # 创建一个正n_items边形的顶点坐标
    radius = 5  # 可以调整半径
    angle = np.linspace(0, 2 * np.pi, n_items, endpoint=False)
    x = radius * np.cos(angle)
    y = radius * np.sin(angle)

    # 绘制正多边形和顶点
    fig, ax = plt.subplots(figsize=(10, 10))

    polygon = patches.RegularPolygon((0, 0), n_items, radius=radius, fill=False, edgecolor='k')
    ax.add_patch(polygon)

    def get_label_position(angle):
        label_offset_value = 0.2  # 定义一个变量来存储偏移量

        # 根据角度确定文本标签的对齐方式和位置
        if angle < np.pi / 2:
            ha, va = "center", "bottom"
            offset = np.array([label_offset_value, label_offset_value])
        elif angle < np.pi:
            ha, va = "center", "bottom"
            offset = np.array([-label_offset_value, label_offset_value])
        elif angle < 3 * np.pi / 2:
            ha, va = "center", "top"
            offset = np.array([-label_offset_value, -label_offset_value])
        else:
            ha, va = "center", "top"
            offset = np.array([label_offset_value, -label_offset_value])
        return ha, va, offset

    # 在绘制顶点的循环中调整文本位置
    for (i, j), label, angle in zip(zip(x, y), items, angle):
        ha, va, offset = get_label_position(angle)
        ax.plot(i, j, 'o', markersize=10)
        ax.text(i + offset[0], j + offset[1], label, fontsize=12, ha=ha, va=va)

    # 获取confidence的最小值和最大值
    min_confidence = rules['confidence'].min()
    max_confidence = rules['confidence'].max()
    # 使用colormap - 可以根据需要选择合适的colormap
    # 这里我们使用'Greens',因为你想要的是颜色越深表示权重越大
    cmap = plt.get_cmap('Greens')

    # 线性映射函数,将confidence值映射到0-1之间,用于colormap
    def get_color(confidence):
        return cmap((confidence - min_confidence) / (max_confidence - min_confidence))

    # 绘制边
    for _, row in rules.iterrows():
        antecedents = row['antecedents']
        consequents = row['consequents']
        confidence = row['confidence']

        for antecedent in antecedents:
            for consequent in consequents:
                start_idx = items.index(antecedent)
                end_idx = items.index(consequent)

                start_point = (x[start_idx], y[start_idx])
                end_point = (x[end_idx], y[end_idx])

                color = get_color(confidence)

                # 修改箭头的绘制方式,使其从节点边缘出发
                ax.annotate("",
                            xy=end_point, xytext=start_point,
                            arrowprops=dict(arrowstyle="->", color=color,
                                            shrinkA=5, shrinkB=5,  # shrinkA和shrinkB应该是半径的大小,不是索引
                                            connectionstyle="arc3"),
                            )

    ax.set_xlim([-radius * 1.1, radius * 1.1])
    ax.set_ylim([-radius * 1.1, radius * 1.1])
    ax.axis('off')  # 隐藏坐标轴

    plt.suptitle('前24个最高频次药物的关联规则图', fontsize=20)  # 主标题
    plt.xlabel('颜色深代表置信度高', fontsize=14)  # X轴标签

    save_path = os.path.join('.', '关联规则网络图.jpg')

    plt.savefig(save_path)
    plt.show()

完整可运行的代码

下方就是完整可运行的代码,在本文的下载链接中也一并包含,如有需要请复制并运行。

py 复制代码
import os

import matplotlib
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

plt.rcParams['font.sans-serif'] = ['Simhei']  # 显示中文标签
plt.rcParams['axes.unicode_minus'] = False

def plot_rules_net(rules: pd.DataFrame):
    import matplotlib.patches as patches

    # 假设你有一个包含所有药材的列表
    items = list(
        set([item for sublist in rules['antecedents'].tolist() + rules['consequents'].tolist() for item in sublist]))

    # 计算药材数量,确定顶点数
    n_items = len(items)

    # 创建一个正n_items边形的顶点坐标
    radius = 5  # 可以调整半径
    angle = np.linspace(0, 2 * np.pi, n_items, endpoint=False)
    x = radius * np.cos(angle)
    y = radius * np.sin(angle)

    # 绘制正多边形和顶点
    fig, ax = plt.subplots(figsize=(10, 10))

    polygon = patches.RegularPolygon((0, 0), n_items, radius=radius, fill=False, edgecolor='k')
    ax.add_patch(polygon)

    def get_label_position(angle):
        label_offset_value = 0.2  # 定义一个变量来存储偏移量

        # 根据角度确定文本标签的对齐方式和位置
        if angle < np.pi / 2:
            ha, va = "center", "bottom"
            offset = np.array([label_offset_value, label_offset_value])
        elif angle < np.pi:
            ha, va = "center", "bottom"
            offset = np.array([-label_offset_value, label_offset_value])
        elif angle < 3 * np.pi / 2:
            ha, va = "center", "top"
            offset = np.array([-label_offset_value, -label_offset_value])
        else:
            ha, va = "center", "top"
            offset = np.array([label_offset_value, -label_offset_value])
        return ha, va, offset

    # 在绘制顶点的循环中调整文本位置
    for (i, j), label, angle in zip(zip(x, y), items, angle):
        ha, va, offset = get_label_position(angle)
        ax.plot(i, j, 'o', markersize=10)
        ax.text(i + offset[0], j + offset[1], label, fontsize=12, ha=ha, va=va)

    # 获取confidence的最小值和最大值
    min_confidence = rules['confidence'].min()
    max_confidence = rules['confidence'].max()
    # 使用colormap - 可以根据需要选择合适的colormap
    # 这里我们使用'Greens',因为你想要的是颜色越深表示权重越大
    cmap = plt.get_cmap('Greens')

    # 线性映射函数,将confidence值映射到0-1之间,用于colormap
    def get_color(confidence):
        return cmap((confidence - min_confidence) / (max_confidence - min_confidence))

    # 绘制边
    for _, row in rules.iterrows():
        antecedents = row['antecedents']
        consequents = row['consequents']
        confidence = row['confidence']

        for antecedent in antecedents:
            for consequent in consequents:
                start_idx = items.index(antecedent)
                end_idx = items.index(consequent)

                start_point = (x[start_idx], y[start_idx])
                end_point = (x[end_idx], y[end_idx])

                color = get_color(confidence)

                # 修改箭头的绘制方式,使其从节点边缘出发
                ax.annotate("",
                            xy=end_point, xytext=start_point,
                            arrowprops=dict(arrowstyle="->", color=color,
                                            shrinkA=5, shrinkB=5,  # shrinkA和shrinkB应该是半径的大小,不是索引
                                            connectionstyle="arc3"),
                            )

    ax.set_xlim([-radius * 1.1, radius * 1.1])
    ax.set_ylim([-radius * 1.1, radius * 1.1])
    ax.axis('off')  # 隐藏坐标轴

    plt.suptitle('前24个最高频次药物的关联规则图', fontsize=20)  # 主标题
    plt.xlabel('颜色深代表置信度高', fontsize=14)  # X轴标签

    save_path = os.path.join('.', '关联规则网络图.jpg')

    plt.savefig(save_path)
    plt.show()



freq = pd.read_excel(r'万条处方的药物出现频次.xlsx')

fd = {k : v for _, (k, v) in freq.iterrows()}

# 指定保留前24最高频次的中药材
most_freq_num = 24
top_24_herbs = sorted(fd, key=lambda x: fd.get(x), reverse=True)[:most_freq_num]

# 读取关联规则分析的结果
rules = pd.read_excel('关联规则分析结果.xlsx')
rules['antecedents'] = rules['antecedents'].apply(lambda x: x.split(', '))
rules['consequents'] = rules['consequents'].apply(lambda x: x.split(', '))

# 过滤关联规则,仅保留包含这24种药物的规则
filtered_rules = rules[rules['antecedents'].apply(lambda x: any(item in x for item in top_24_herbs)) &
                       rules['consequents'].apply(lambda x: any(item in x for item in top_24_herbs))]

plot_rules_net(filtered_rules)

运行结果

颜色越粗,置信度越高。

我们可以看到砂仁和白芍,还有荷叶和连翘等等,有着很高的置信度。

相关推荐
Highcharts.js2 天前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化
lisw052 天前
互联网上的数据结构可视化!
数据结构·信息可视化
Elastic 中国社区官方博客3 天前
基于 Elasticsearch 与 Jina AI 的全模态智能搜索实践:技术全解析
大数据·人工智能·elasticsearch·搜索引擎·ai·信息可视化·jina
Teable任意门互动4 天前
破解多平台数据不通!江浙沪跨境电商外贸业务私有化部署方案|任意门互动科技
大数据·人工智能·科技·信息可视化·信息与通信
工业HMI实战笔记5 天前
皮革加工HMI:制革鞣制的化工参数界面
信息可视化·设计规范·设计语言
IT研究室5 天前
最新大数据毕业设计选题推荐-基于大数据的Medicaid GLP-1药物利用与支出数据可视化分析-大数据-Spark-Hadoop-Bigdata
大数据·信息可视化·课程设计
雨晨源码(同名B站)5 天前
深度学习毕业设计选题推荐:基于卷积神经网络的无人机影像建筑裂缝裂纹检测分类与分割系统(LeNet-5 二分类模型、GCN-Res50分割模型)
深度学习·信息可视化·分类·cnn·毕业设计·无人机·课程设计
龙亘川5 天前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
新中地GIS开发老师6 天前
资源与环境(地理信息工程)这个专业怎么样
考研·信息可视化·资源与环境
fanruitian7 天前
python 可视化 panda seaborn matplotlib.pyplot
开发语言·python·matplotlib