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
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!











