You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
4.3 KiB

4 months ago
from pyecharts.charts import Bar, Pie
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
import os
5 months ago
4 months ago
def generate_chart(
_data,
chart_type: str, # 图表类型:'bar' 或 'pie'
title: str, # 图表标题
category_columns: list, # 分类数据列X 轴或饼图标签)
value_column: str, # 数值数据列Y 轴或饼图值)
output_file: str = "chart.html" # 输出文件路径
):
5 months ago
"""
4 months ago
统一生成柱形图或饼形图
5 months ago
参数:
4 months ago
_data: 结果集通常是一个列表字典格式
chart_type (str): 图表类型'bar' 'pie'
title (str): 图表标题
category_columns (list): 分类数据列X 轴或饼图标签
value_column (str): 数值数据列Y 轴或饼图值
output_file (str): 输出 HTML 文件名默认 "chart.html"
5 months ago
"""
try:
# 如果结果集为空,直接返回
5 months ago
if not _data:
5 months ago
raise ValueError("结果集为空,无法生成图表!")
# 检查列名是否存在
4 months ago
for col in category_columns + [value_column]:
5 months ago
if col not in _data[0]:
5 months ago
raise ValueError(f"列名 '{col}' 不存在!")
4 months ago
# 提取分类数据(动态组合多列)
categories = [" - ".join(str(row[col]) for col in category_columns) for row in _data]
# 提取数值数据
values = [row[value_column] for row in _data]
5 months ago
4 months ago
# 颜色配置
5 months ago
colors = [
"#5470C6", "#91CC75", "#EE6666", "#73C0DE", "#3BA272", "#FC8452", "#9A60B4", "#EA7CCC"
4 months ago
]
color_js = JsCode(f'''
function(params) {{
var colorList = {colors};
return colorList[params.dataIndex % colorList.length];
}}
''')
# 生成柱形图
if chart_type == 'bar':
chart = Bar()
chart.add_xaxis(categories)
chart.add_yaxis(
series_name=value_column,
y_axis=values,
bar_width="30%",
itemstyle_opts=opts.ItemStyleOpts(color=color_js)
)
chart.set_global_opts(
title_opts=opts.TitleOpts(title=title),
xaxis_opts=opts.AxisOpts(
name=" - ".join(category_columns),
axislabel_opts=opts.LabelOpts(rotate=45),
boundary_gap=True,
splitline_opts=opts.SplitLineOpts(is_show=False)
),
yaxis_opts=opts.AxisOpts(name=value_column),
legend_opts=opts.LegendOpts(is_show=False)
)
5 months ago
4 months ago
# 生成饼形图
elif chart_type == 'pie':
data_pairs = list(zip(categories, values))
chart = Pie()
chart.add(
series_name="占比",
data_pair=data_pairs,
radius=["30%", "55%"],
label_opts=opts.LabelOpts(
formatter="{b}\n{d}%",
position="outside",
font_size=14
),
itemstyle_opts=opts.ItemStyleOpts(color=color_js)
)
chart.set_global_opts(
title_opts=opts.TitleOpts(
title=title,
subtitle="数据维度:" + "".join(category_columns)
),
legend_opts=opts.LegendOpts(is_show=False)
5 months ago
)
4 months ago
else:
raise ValueError("不支持的图表类型!")
5 months ago
# 确保目标目录存在
4 months ago
os.makedirs(os.path.dirname(output_file), exist_ok=True)
5 months ago
# 保存为 HTML 文件
4 months ago
# 保存为 HTML 文件,并替换默认标题
chart.render(
path=output_file,
#template_name="simple_chart.html", # 使用自定义模板
title="长春云校数据统计" # 替换默认标题
)
4 months ago
print(f"图表已保存为 {output_file}")
5 months ago
# 检查文件是否存在
if os.path.exists(output_file):
print("文件生成成功!")
else:
print("文件生成失败!")
5 months ago
except Exception as e:
4 months ago
print(f"生成图表时发生错误: {e}")