Python使用策略模式实现绘图功能

策略模式(Strategy Pattern):允许定义一系列算法,将它们封装起来,使得它们可以互换。

实现绘制不同类型的图表(如折线图、柱状图和饼图)功能。

下面是一个示例,展示如何传入横坐标和纵坐标内容,然后绘制不同类型的图表。




import matplotlib.pylab as plt
from abc import ABC, abstractmethod

class PlotStrategy(ABC):
    # 抽象类:强制子类实现此方法
    @abstractmethod
    def plot(self, x_data, y_data, desc):
        pass

class LinePlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        print('折线图')
        plt.plot(x_data,y_data,marker=0)
        plt.title(desc[0])
        plt.xlabel(desc[1])
        plt.ylabel(desc[2])
        plt.show()

class BarPlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        print('柱状图')
        plt.bar(x_data, y_data)
        plt.title(desc[0])
        plt.xlabel(desc[1])
        plt.ylabel(desc[2])
        plt.show()

class PiePlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        print('饼图')
        labels = x_data
        sizes = y_data
        plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=140)
        plt.axis('equal') # 正圆形
        plt.title(desc[0])
        plt.show()


# Context类持有PlotStrategy的引用。可以通过set_strategy方法动态地更改策略
class Context:
    def __int__(self, strategy: PlotStrategy):
        # _ 开头的变量,表示这是一个受保护的变量
        # 该变量只在类内部及其子类中使用,而不应在类外部直接访问
        self._strategy = strategy

    def set_strategy(self,strategy: PlotStrategy):
        self._strategy = strategy

    def execute_strategy(self, x_data, y_data, desc):
        self._strategy.plot(x_data, y_data, desc)


x = ['A','B','C']
y = [2,3,6]
desc = ['title','x','y']

# line = LinePlotStrategy().plot(x, y, desc)
# bar = BarPlotStrategy().plot(x,  y, desc)
# pie = PiePlotStrategy().plot(x,  y, desc)

context = Context()

context.set_strategy(LinePlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(BarPlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(PiePlotStrategy())
context.execute_strategy(x,  y, desc)

折线图
柱状图
饼图


import matplotlib.pylab as plt
from abc import ABC, abstractmethod
import seaborn as sns
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio
import altair as alt
from bokeh.plotting import figure, output_file, show
from bokeh.io import output_file,show
from bokeh.palettes import Category20c
from bokeh.plotting import figure, show
from bokeh.transform import cumsum
from math import pi

class PlotStrategy(ABC):
    # 抽象类:强制子类实现此方法
    @abstractmethod
    def plot(self, x_data, y_data, desc):
        pass

class LinePlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        print('折线图')
        plt.clf()  # 清除当前图形内容
        plt.plot(x_data,y_data,color='blue', linestyle='-', linewidth=2, marker='o', markersize=6, label='sin(x)')
        plt.title(desc[0], fontsize=16)
        plt.xlabel(desc[1], fontsize=14)
        plt.ylabel(desc[2], fontsize=14)

        plt.xticks(fontsize=12)
        plt.yticks(fontsize=12)

        plt.legend(fontsize=12)  # 添加图例

        plt.grid(True)  # 添加网格
        plt.tight_layout()  # 自动调整布局
        # plt.show()
        plt.savefig('./line.png')

class BarPlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        plt.clf()  # 清除当前图形内容
        print('柱状图')
        bars = plt.bar(x_data, y_data,color='skyblue', edgecolor='grey')
        plt.title(desc[0], fontsize=16)
        plt.xlabel(desc[1], fontsize=14)
        plt.ylabel(desc[2], fontsize=14)
        # 添加数值标签
        for bar in bars:
            plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height(),
                     round(bar.get_height(), 1), ha='center', va='bottom')
        plt.xticks(fontsize=12)
        plt.yticks(fontsize=12)
        plt.tight_layout()  # 自动调整布局
        # plt.show()
        plt.savefig('./bar.png')

class PiePlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        plt.clf()# 清除当前图形内容
        print('饼图')
        labels = x_data
        sizes = y_data
        plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=140)
        plt.axis('equal') # 正圆形
        plt.title(desc[0])
        # plt.show()
        plt.savefig('./pie.png')

class SeabornPlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        plt.clf()  # 清除当前图形内容
        print('Seaborn数据可视化库生成折线图')
        # Seaborn 是基于 matplotlib 的数据可视化库,提供了更高层次的接口,使得统计数据可视化更加简单和美观
        sns.lineplot(x = x_data,y = y_data)
        # plt.show()
        plt.savefig('./line_seaborn.png')

        plt.clf()  # 清除当前图形内容
        print('Seaborn数据可视化库生成柱状图')
        # 示例数据
        data = {'Category': x_data,'Values': y_data}
        # 创建一个 DataFrame
        df = pd.DataFrame(data)
        sns.barplot(x='Category', y='Values', data=df)
        # plt.show()
        plt.savefig('./bar_seaborn.png')

class PlotlyPlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        print('使用 Plotly 画折线图')
        # 使用 Plotly 画折线图,Plotly 是一个交互式可视化库,支持绘制高质量的动态图表和仪表板。它可以生成 HTML 文件或者在线展示
        fig = go.Figure(data=go.Scatter(x=x_data, y=y_data))
        # fig.show()
        # 需要安装 kaleido 这个附加依赖,它是 Plotly 的推荐渲染引擎
        # pio.write_image(fig, './line_plotly.png') # 执行失败,执行到此步骤 长时间无响应
        # fig.write_image('./line_plotly.png')      # 执行失败,执行到此步骤 长时间无响应
        fig.write_html('./line_plotly.html')

        print('使用 Plotly 画柱状图')
        fig = go.Figure(data=go.Bar(x=x_data, y=y_data))
        fig.update_layout(
            title=desc[0],
            xaxis=dict(title=desc[1]),
            yaxis=dict(title=desc[2])
        )
        # fig.show()
        fig.write_html('./bar_plotly.html')

        print('使用 Plotly 画饼图')
        fig = go.Figure(data=go.Pie(labels=x_data, values=y_data))
        fig.update_layout(
            title=desc[0]
        )
        # fig.show()
        fig.write_html('./pie_plotly.html')

class AltairPlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        # Altair 是一个 Python 可视化库,使用简洁的声明式语法创建交互式可视化
        print('使用 Altair 画折线图')
        # 创建示例数据
        data = pd.DataFrame({
            'x': x_data,
            'y': y_data
        })
        # 创建折线图
        line_chart = alt.Chart(data).mark_line().encode(
            x='x',
            y='y'
        ).properties(
            title=desc[0]
        )
        # 显示折线图
        line_chart.save('./line_altair.html')

        print('使用 Altair 画柱状图')
        # 创建示例数据
        data = pd.DataFrame({
            'x': x_data,
            'y': y_data
        })

        # 创建柱状图
        bar_chart = alt.Chart(data).mark_bar().encode(
            x='x',
            y='y'
        ).properties(
            title=desc[0]
        )
        # 显示柱状图
        bar_chart.save('./bar_altair.html')

        print('使用 Altair 画饼图')
        # 创建示例数据
        data = pd.DataFrame({
            'category': x_data,
            'value': y_data
        })
        # 计算百分比
        data['percent'] = (data['value'] / (data['value'].sum()) * 100).round(2)
        # 创建饼图
        pie_chart = alt.Chart(data).mark_arc(
            size=200,  # 设置饼图的大小
            outerRadius=150  # 设置饼图半径
        ).encode(
            theta='value:Q',  # 角度根据value列的值来编码
            color='category:N',  # 颜色根据category列的值来编码
            tooltip=['category', 'percent:Q'],  # tooltip显示category和percent列
        ).properties(
            width=300,
            height=300,
            title=desc[0]
        )
        # 显示饼图,Altair 不直接支持在每个扇区上显示两个不同的文本标签(值和百分比)
        pie_chart.save('./pie_altair.html')


class BokehPlotStrategy(PlotStrategy):
    def plot(self, x_data, y_data, desc):
        # 使用 Bokeh 画折线图,Plotly 是一个交互式的可视化库,可以生成漂亮的图表,并支持与用户交互,例如缩放、悬停等操作
        # 官方文档:https://docs.bokeh.org/en/latest/docs/user_guide/basic/lines.html
        print('使用 Bokeh 画折线图')
        # # 创建绘图对象
        # output_file("./line_bokeh.html")
        # p = figure(width=400, height=400)
        #
        # # add a line renderer
        # p.line(x_data, y_data, line_width=2)
        # # 显示图表
        # show(p)

        print('使用 Bokeh 画柱状图')
        p = figure(x_range=x_data, height=350, title=desc[0],toolbar_location=None, tools="")
        p.vbar(x=x_data, top=y_data, width=0.9)
        p.xgrid.grid_line_color = None
        p.y_range.start = 0
        output_file("./bar_bokeh.html")
        show(p)

        print('使用 Bokeh 画饼图')
        categories = x_data  # 图例标签
        values = y_data  # 饼图的数值
        # 计算起始和结束角度
        start_angles = [2 * pi * i / sum(values) for i, _ in enumerate(values[:-1])]
        end_angles = [2 * pi * (i + 1) / sum(values) for i, _ in enumerate(values)]

        # 创建绘图对象
        p = figure(title=desc[0], x_axis_type=None, y_axis_type=None, toolbar_location=None)

        # 绘制饼图,确保legend_label是字符串
        for i, (start, end, cat) in enumerate(zip(start_angles, end_angles, categories)):
            p.wedge(x=0, y=1, radius=0.8,
                    start_angle=start, end_angle=end,
                    line_color="white", fill_color="blue",  # 可以为每个扇形设置不同的颜色
                    legend_label=str(cat))  # 确保legend_label是字符串

        # 添加图例
        p.legend.location = "top_right"
        p.legend.click_policy = "hide"  # 可选:点击图例项来隐藏/显示对应的图形
        # 显示图表
        output_file("pie_bokeh.html")
        show(p)



# Context类持有PlotStrategy的引用。可以通过set_strategy方法动态地更改策略
class Context:
    def __int__(self, strategy: PlotStrategy):
        # _ 开头的变量,表示这是一个受保护的变量
        # 该变量只在类内部及其子类中使用,而不应在类外部直接访问
        self._strategy = strategy

    def set_strategy(self,strategy: PlotStrategy):
        self._strategy = strategy

    def execute_strategy(self, x_data, y_data, desc):
        self._strategy.plot(x_data, y_data, desc)


x = ['A','B','C','D','E','F','G']
y = [2,3,6,1,4,4,3]
x1 = [1,2,3,4,5,6,7]
desc = ['title','x','y']

# line = LinePlotStrategy().plot(x, y, desc)
# bar = BarPlotStrategy().plot(x,  y, desc)
# pie = PiePlotStrategy().plot(x,  y, desc)
# seab = SeabornPlotStrategy().plot(x,y,desc)

context = Context()

context.set_strategy(LinePlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(BarPlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(PiePlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(SeabornPlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(PlotlyPlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(AltairPlotStrategy())
context.execute_strategy(x,  y, desc)

context.set_strategy(BokehPlotStrategy())
context.execute_strategy(x,  y, desc)

折线图
柱状图
饼图
Seaborn数据可视化库生成折线图
Seaborn数据可视化库生成柱状图
使用 Plotly 画折线图
使用 Plotly 画柱状图
使用 Plotly 画饼图
使用 Altair 画折线图
使用 Altair 画柱状图
使用 Altair 画饼图
使用 Bokeh 画折线图
使用 Bokeh 画柱状图
使用 Bokeh 画饼图

网格和布局 — Bokeh 3.4.1 文档

 

Specifying Data — Vega-Altair 5.3.0 documentation (altair-viz.github.io)

 

Plotly Python 图形库

Python API 参考 plotly — 5.22.0 文档

 Seaborn:统计数据可视化 — Seaborn 0.13.2 文档 (pydata.org)

API reference — seaborn 0.13.2 documentation

User guide and tutorial — seaborn 0.13.2 documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/727778.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot集成tablesaw插件快速入门

1 什么是tablesaw? Tablesaw是一款Java的数据可视化库,主要包括两部分: 数据解析库,主要用于加载数据,对数据进行操作(转化,过滤,汇总等),类比Python中的Pandas库; 数据…

JVM中的垃圾回收机制

文章目录 什么是垃圾为什么需要垃圾回收早期垃圾回收Java的垃圾回收机制垃圾回收主要关注的区域垃圾判定算法引用计数算法可达性分析算法 垃圾收集算法标记清除算法复制算法标记整理算法分代收集思想增量收集算法分区算法 什么是垃圾 垃圾回收(Garbage Collection&…

Java面试八股之Mybatis和JPA的区别

Mybatis和JPA的区别 Mybatis 和 JPA(Java Persistence API)是两种在 Java 应用程序中用于数据持久化的框架,它们各有特点和适用场景。下面是它们之间的一些主要区别: 映射方式: Mybatis 是半自动的 ORM 框架&#xf…

Vue66-vue-默认插槽

一、默认插槽需求 1-1、原本的写法: 在每个category组件中用v-show来做条件渲染,但是不方便! 1-2、默认插槽 img标签,ul标签,video标签,都是在app组件中完成解析之后,塞到category组件中的&…

实验室装修公司教你:真菌实验室设计建设的必备技巧

在当今的科学研究和生物技术领域,真菌实验室设计建设显得尤为重要。然而,很多实验室在实际操作中常常面临空间布局不合理、设备配置不当以及环境控制不到位等诸多挑战,导致实验效率低下,甚至危及人员安全。那么要怎么才能设计建设…

【Unity】AssetBundle打包策略

【Unity】AssetBundle打包策略 在游戏开发过程中,AssetBundle(AB)打包策略的重要性不容忽视。游戏开发者往往手动设置游戏资源包名进行管理,难免会造成资源确实或导致冗余,因此对于AB包的打包流程来说,进行策略管理显得十分重要。…

卓越的 App UI 风格引领潮流

卓越的 App UI 风格引领潮流

fastadmin多语言切换设置

fastadmin版本:1.4.0.20230711 以简体,繁体,英文为例 一,在application\config.php 里开启多语言 // 是否开启多语言lang_switch_on > true, // 允许的语言列表allow_lang_list > [zh-cn, en,zh-tw], 二…

Linux环境编程基础学习2

For循环累加求和,两种方式,c方式的运算更快 打开文件操作 cat操作的实现 EOF: 1.diff A B比较两个文件是否一样,一样则什么结果都没有 Od -c 文件名可以显示出文件中的不可见字符

Stable Diffusion WebUI 使用ControlNet:IP-Adapter保持生图的角色一致性

IP-Adapter-FaceID可以在保持人脸一致的条件下生成各种风格的图像。 下载 IP Adapter 需要的 Face ID 模型和 Lora 下载地址:https://huggingface.co/h94/IP-Adapter-FaceID/ 下载 ip-adapter-faceid-plusv2_sd15.bin 和 ip-adapter-faceid-plusv2_sd15_lora.saf…

Linux:文件描述符

文件描述符实际上就是一个小整数 0 & 1 & 2 Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2. 0,1,2对应的物理设备一般是:键盘,显示器,显示器 所以输入输…

SpingBoot快速入门下

响应HttpServietResponse 介绍 将ResponseBody 加到Controller方法/类上 作用:将方法返回值直接响应,如果返回值是 实体对象/集合,将会自动转JSON格式响应 RestController Controller ResponseBody; 一般响应 统一响应 在实际开发中一般…

多线程下JVM内存模型 和 volatile关键字

1、线程的概念 线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务…

20240620每日一题-测试瓶子的硬度

小明用2个玻璃瓶,在总高88层大楼测试瓶子硬度,拿1个瓶子从某层摔下去,瓶子没摔碎,到更高层去摔,如果碎了,拿另1瓶子到更低层摔 问测试出瓶子最大硬度最少摔几次? 分析 1只有1个瓶子 为了保证…

C语言数据存储大小端问题

大小端 什么是大小端 大端模式(Big-endian),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中; 小端模式(Little-endian),是指数据的高字…

静态网页处理复杂请求

目录 1.定制请求头 (1).查看请求头 (2).设置请求头 2.验证 Cookie 3.保持会话 4. SSL 证书验证 在互联网中,网页中的内容是千变万化的,如果只根据请求 URL 发送基本请求,则可能 无法获取网站的响应数据&#xff0…

基 CanMV 的 C 开发环境搭建(Linux,Ubuntu篇)

不论是使用 CanMV 提供的基于 C 语言和 FreeRTOS 的应用开发方式开发应用程序或是编译 CanMV 固件,都需要搭建基于 CanMV 的 C 开发环境,用于编译 CanMV 源码。 1. 开发环境搭建说明 CanMV 提供了基于 C 语言和 FreeRTOS 的应用开发…

如何调用讯飞星火认知大模型的API以利用其卓越功能

摘要 讯飞星火认知大模型,作为科大讯飞精心打造的一款人工智能模型,在自然语言理解和生成方面展现出了卓越的能力。这款模型通过深度学习技术和大量数据的训练,具备了强大的语言理解、文本生成和对话交互等功能。 一、模型功能概述 讯飞星…

XXL-Job实战(一)

​需求介绍:构建一个分布式短信发送系统,应对双十一活动需向1000万用户快速推送营销短信的挑战,每条数据的业务处理逻辑为0.1s。对于普通任务来说,只有一个线程来处理 可能需要10万秒才能处理完,业务则严重受影响。 常…

【Maven】项目的Maven插件报错

1. 找到本地maven库 2. 删除本地插件 3. 在IDEA上更新pom.xml