1490 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			1490 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			Python
		
	
	
	
| # -*- coding: utf-8 -*-
 | ||
| 
 | ||
| """
 | ||
| 
 | ||
| 扩展PANDAS常用功能
 | ||
| 
 | ||
| """
 | ||
| 
 | ||
| # 加载模块
 | ||
| 
 | ||
| from pathlib import Path
 | ||
| 
 | ||
| import pandas
 | ||
| 
 | ||
| from prettytable import PrettyTable
 | ||
| 
 | ||
| from openpyxl import Workbook
 | ||
| 
 | ||
| from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
 | ||
| 
 | ||
| from openpyxl.utils import get_column_letter
 | ||
| 
 | ||
| from pyecharts import __file__ as default_path, options
 | ||
| 
 | ||
| from pyecharts.components import Table
 | ||
| 
 | ||
| from pyecharts.charts import Scatter, Pie, Bar, Line, HeatMap
 | ||
| 
 | ||
| from pyecharts.globals import ThemeType, CurrentConfig
 | ||
| 
 | ||
| from jinja2 import Environment, FileSystemLoader
 | ||
| 
 | ||
| 
 | ||
| def open_csv(file_name):
 | ||
|     """打开并读取CSV文件,返回数据体"""
 | ||
| 
 | ||
|     # 创建路径对象
 | ||
|     file_path = Path(file_name)
 | ||
| 
 | ||
|     if not file_path.exists():
 | ||
| 
 | ||
|         raise FileNotFoundError(f"路径({file_path})不存在")
 | ||
| 
 | ||
|     if not file_path.is_file():
 | ||
| 
 | ||
|         raise IsADirectoryError(f"路径({file_path})非文件")
 | ||
| 
 | ||
|     if file_path.suffix.lower() != ".csv":
 | ||
| 
 | ||
|         raise ValueError(f"文件名后缀({file_path.suffix.lower()})非CSV")
 | ||
| 
 | ||
|     # 使用PANDAS读取CSV文件并返回
 | ||
|     return pandas.read_csv(
 | ||
|         filepath_or_buffer=file_path,
 | ||
|         # 指定所有列数据类型为字符串(后续人工处理数据类型)
 | ||
|         dtype=str,
 | ||
|         encoding="utf-8",
 | ||
|         # 若遇行解析错误则抛出PARSERERROR
 | ||
|         on_bad_lines="error",
 | ||
|     )
 | ||
| 
 | ||
| 
 | ||
| def traverse_directory(directory_path, suffixes):
 | ||
|     """遍历目录根据文件名后缀读取文件,返回数据体"""
 | ||
| 
 | ||
|     # 创建路径对象
 | ||
|     directory_path = Path(directory_path)
 | ||
| 
 | ||
|     if not directory_path.exists():
 | ||
| 
 | ||
|         raise FileNotFoundError(f"路径({directory_path})不存在")
 | ||
| 
 | ||
|     if not directory_path.is_dir():
 | ||
| 
 | ||
|         raise NotADirectoryError(f"路径({directory_path})非目录")
 | ||
| 
 | ||
|     if not isinstance(suffixes, list):
 | ||
| 
 | ||
|         raise TypeError("文件名后缀(suffixes)数据类型非列表")
 | ||
| 
 | ||
|     dataframe = []
 | ||
| 
 | ||
|     for file_path in directory_path.rglob("*"):
 | ||
| 
 | ||
|         if file_path.is_file() and file_path.suffix.lower() in suffixes:
 | ||
| 
 | ||
|             dataframe.append(
 | ||
|                 {
 | ||
|                     "文件名": file_path.name,
 | ||
|                     "父目录": file_path.parent.name,
 | ||
|                     "相对路径": str(file_path.relative_to(".")),
 | ||
|                 }
 | ||
|             )
 | ||
| 
 | ||
|     # 创建并返回数据体
 | ||
|     return pandas.DataFrame(dataframe).sort_values(by=["父目录", "文件名"])
 | ||
| 
 | ||
| 
 | ||
| def save_as_workbook(worksheets, workbook_name):
 | ||
|     """将数据体保存为工作簿"""
 | ||
| 
 | ||
|     # 创建工作簿
 | ||
|     workbook = Workbook()
 | ||
| 
 | ||
|     # 删除默认创建的工作表
 | ||
|     for worksheet_name in workbook.sheetnames:
 | ||
| 
 | ||
|         workbook.remove(workbook[worksheet_name])
 | ||
| 
 | ||
|     for worksheet_name, worksheet_dataframe in worksheets:
 | ||
| 
 | ||
|         # 若工作表数据体为空则跳过
 | ||
|         if not worksheet_dataframe.empty:
 | ||
| 
 | ||
|             # 创建工作表
 | ||
|             worksheet = workbook.create_sheet(title=worksheet_name)
 | ||
| 
 | ||
|             # 若为多层行索引则重置行索引(单层行索引则跳过)
 | ||
|             if isinstance(worksheet_dataframe.index, pandas.MultiIndex):
 | ||
| 
 | ||
|                 worksheet_dataframe.reset_index(inplace=True)
 | ||
| 
 | ||
|             # 遍历列索引层
 | ||
|             for level in range(worksheet_dataframe.columns.nlevels):
 | ||
| 
 | ||
|                 # 添加列名行
 | ||
|                 worksheet.append(
 | ||
|                     worksheet_dataframe.columns.get_level_values(level).tolist()
 | ||
|                 )  # 工作表一般包括标题行、列名行和数据行,在这里仅考虑列名行和数据行
 | ||
| 
 | ||
|                 # 初始化合并单元格开始列号
 | ||
|                 merge_start_column = 0
 | ||
| 
 | ||
|                 # 初始化上一个单元格值
 | ||
|                 previous_cell_value = worksheet.cell(
 | ||
|                     row=level + 1, column=merge_start_column + 1
 | ||
|                 ).value
 | ||
| 
 | ||
|                 for column in range(
 | ||
|                     len(worksheet_dataframe.columns.get_level_values(level))
 | ||
|                 ):
 | ||
| 
 | ||
|                     # 单元格值
 | ||
|                     value = worksheet.cell(
 | ||
|                         row=level + 1, column=column + 1
 | ||
|                     ).value  # 工作表数据体为PANDAS.DATAFRAME,行号和列号从0开始,工作表为OPENPYXL,行号和列号从1开始
 | ||
| 
 | ||
|                     if value != previous_cell_value:
 | ||
| 
 | ||
|                         # 合并单元格结束列号
 | ||
|                         merge_end_column = column - 1
 | ||
| 
 | ||
|                         # 判断合并单元格结束列号和合并单元格开始列号的差值是否大于0
 | ||
|                         if (
 | ||
|                             previous_cell_value
 | ||
|                             and merge_end_column - merge_start_column > 0
 | ||
|                         ):
 | ||
| 
 | ||
|                             # 合并单元格(同行合并)
 | ||
|                             worksheet.merge_cells(
 | ||
|                                 start_row=level + 1,
 | ||
|                                 end_row=level + 1,
 | ||
|                                 start_column=merge_start_column + 1,
 | ||
|                                 end_column=merge_end_column + 1,
 | ||
|                             )
 | ||
| 
 | ||
|                         # 重新赋值合并单元格开始列号
 | ||
|                         merge_start_column = column
 | ||
| 
 | ||
|                         # 重新赋值上一单元格值
 | ||
|                         previous_cell_value = value
 | ||
| 
 | ||
|                     # 若单元格值和上一个单元格值相同,若列号为最大值则合并单元格
 | ||
|                     else:
 | ||
| 
 | ||
|                         # 判断列号是否为最大值
 | ||
|                         if (
 | ||
|                             column
 | ||
|                             == len(worksheet_dataframe.columns.get_level_values(level))
 | ||
|                             - 1
 | ||
|                         ):
 | ||
| 
 | ||
|                             # 重新赋值合并单元格结束列号
 | ||
|                             merge_end_column = column
 | ||
| 
 | ||
|                             # 合并单元格(同行合并)
 | ||
|                             worksheet.merge_cells(
 | ||
|                                 start_row=level + 1,
 | ||
|                                 end_row=level + 1,
 | ||
|                                 start_column=merge_start_column + 1,
 | ||
|                                 end_column=merge_end_column + 1,
 | ||
|                             )
 | ||
| 
 | ||
|                     # 若单元格值为空则同列合并
 | ||
|                     if not value:
 | ||
| 
 | ||
|                         # 合并单元格(同列合并)
 | ||
|                         worksheet.merge_cells(
 | ||
|                             start_row=level,
 | ||
|                             end_row=level + 1,
 | ||
|                             start_column=column + 1,
 | ||
|                             end_column=column + 1,
 | ||
|                         )
 | ||
| 
 | ||
|             # 工作表列宽:24磅
 | ||
|             for column in range(worksheet_dataframe.shape[1]):
 | ||
| 
 | ||
|                 worksheet.column_dimensions[get_column_letter(column + 1)].width = 24
 | ||
| 
 | ||
|             # 列名行行高:24磅
 | ||
|             for level in range(worksheet_dataframe.columns.nlevels):
 | ||
| 
 | ||
|                 worksheet.row_dimensions[level + 1].height = 24
 | ||
| 
 | ||
|                 # 列名行单元格样式
 | ||
|                 for column in range(
 | ||
|                     len(worksheet_dataframe.columns.get_level_values(level))
 | ||
|                 ):
 | ||
| 
 | ||
|                     cell = worksheet.cell(level + 1, column + 1)
 | ||
| 
 | ||
|                     # 字体
 | ||
|                     cell.font = Font(bold=True, size=12, name="Arial", color="00FFFFFF")
 | ||
| 
 | ||
|                     # 对齐方式
 | ||
|                     cell.alignment = Alignment(horizontal="center", vertical="center")
 | ||
| 
 | ||
|                     # 边框
 | ||
|                     cell.border = Border(
 | ||
|                         left=Side(style="thin", color="00333333"),
 | ||
|                         right=Side(style="thin", color="00333333"),
 | ||
|                         top=Side(style="thin", color="00333333"),
 | ||
|                         bottom=Side(style="thin", color="00333333"),
 | ||
|                     )
 | ||
| 
 | ||
|                     # 填充
 | ||
|                     cell.fill = PatternFill(fill_type="solid", start_color="003366FF")
 | ||
| 
 | ||
|             for row, row_data in worksheet_dataframe.iterrows():
 | ||
| 
 | ||
|                 # 数据行行高:20磅
 | ||
|                 worksheet.row_dimensions[
 | ||
|                     row + worksheet_dataframe.columns.nlevels + 1
 | ||
|                 ].height = 20
 | ||
| 
 | ||
|                 for column in range(worksheet_dataframe.shape[1]):
 | ||
| 
 | ||
|                     cell = worksheet.cell(
 | ||
|                         row + worksheet_dataframe.columns.nlevels + 1, column + 1
 | ||
|                     )
 | ||
| 
 | ||
|                     # 单元格值
 | ||
|                     cell.value = row_data.iloc[column]
 | ||
| 
 | ||
|                     # 字体
 | ||
|                     cell.font = Font(size=12, name="Arial", color="00333333")
 | ||
| 
 | ||
|                     # 对齐方式
 | ||
|                     cell.alignment = Alignment(horizontal="center", vertical="center")
 | ||
| 
 | ||
|                     cell.border = Border(
 | ||
|                         left=Side(style="thin", color="00333333"),
 | ||
|                         right=Side(style="thin", color="00333333"),
 | ||
|                         top=Side(style="thin", color="00333333"),
 | ||
|                         bottom=Side(style="thin", color="00333333"),
 | ||
|                     )
 | ||
| 
 | ||
|     workbook.save(workbook_name)
 | ||
| 
 | ||
| 
 | ||
| def print_table(dataframe, index_as_the_first_column=False, title=None, remark=None):
 | ||
|     """将数据体打印为表格"""
 | ||
| 
 | ||
|     dataframe_temporary = dataframe.copy()
 | ||
| 
 | ||
|     table = PrettyTable()
 | ||
| 
 | ||
|     # 若索引作为第一列,则重置数据集索引
 | ||
|     if index_as_the_first_column:
 | ||
| 
 | ||
|         # 重置索引
 | ||
|         dataframe_temporary.reset_index(inplace=True)
 | ||
| 
 | ||
|         # 修改第一列列名
 | ||
|         dataframe_temporary.rename(columns={"index": ""}, inplace=True)
 | ||
| 
 | ||
|     # 列标签
 | ||
|     column_labels = dataframe_temporary.columns.tolist()
 | ||
| 
 | ||
|     # 赋值给表格列标签
 | ||
|     table.field_names = column_labels
 | ||
| 
 | ||
|     # 行数据(若数据类型为浮点则保留两位小数并转为字符)
 | ||
|     row_data = dataframe_temporary.map(
 | ||
|         lambda x: f"{x:.2f}" if isinstance(x, float) else x
 | ||
|     ).to_numpy()
 | ||
| 
 | ||
|     # 赋值给表格行数据
 | ||
|     table.add_rows(row_data)
 | ||
| 
 | ||
|     # 第一列左对齐,其余列右对齐
 | ||
|     table.align[column_labels[0]] = "l"
 | ||
| 
 | ||
|     for column_label in column_labels[1:]:
 | ||
| 
 | ||
|         table.align[column_label] = "r"
 | ||
| 
 | ||
|     # 若表格标题数据类型为字符则打印
 | ||
|     if isinstance(title, str):
 | ||
| 
 | ||
|         print(title)
 | ||
| 
 | ||
|     print(table)
 | ||
| 
 | ||
|     # 若表格备注数据类型为字符则打印
 | ||
|     if isinstance(remark, str):
 | ||
| 
 | ||
|         print(remark)
 | ||
| 
 | ||
| 
 | ||
| class DrawAsHTML:
 | ||
| 
 | ||
|     def __init__(self):
 | ||
|         """绘制图表并保存为HTML"""
 | ||
| 
 | ||
|         # 全局网页标题
 | ||
|         CurrentConfig.PAGE_TITLE = "DrawAsHTML"
 | ||
| 
 | ||
|         # 全局环境
 | ||
|         CurrentConfig.GLOBAL_ENV = Environment(
 | ||
|             loader=FileSystemLoader(
 | ||
|                 [
 | ||
|                     Path(default_path).parent / "render" / "templates",  # 默认模版路径
 | ||
|                     Path(__file__).parent / "templates",  # 自定义模版路径
 | ||
|                 ]
 | ||
|             )
 | ||
|         )
 | ||
| 
 | ||
|     @staticmethod
 | ||
|     def table(dataframe: pandas.DataFrame, file_name: str) -> None:
 | ||
|         """表格"""
 | ||
| 
 | ||
|         # 创建表格,HTML标题默认为全局网页标题
 | ||
|         chart = Table(page_title=CurrentConfig.PAGE_TITLE)
 | ||
| 
 | ||
|         chart.add(
 | ||
|             # 表格表头
 | ||
|             headers=dataframe.columns.tolist(),
 | ||
|             # 表格数据
 | ||
|             rows=dataframe.values.tolist(),
 | ||
|         )
 | ||
| 
 | ||
|         chart.render(
 | ||
|             template_name="table.html",
 | ||
|             html_content=chart.html_content,
 | ||
|             path=file_name,
 | ||
|         )
 | ||
| 
 | ||
|     # 直角坐标系图表
 | ||
| 
 | ||
|     def scatter(
 | ||
|         self,
 | ||
|         dataframe: pandas.DataFrame,
 | ||
|         file_name: str,
 | ||
|         xaxis_opts_min: int | float | None = None,
 | ||
|         xaxis_opts_max: int | float | None = None,
 | ||
|         yaxis_opts_min: int | float | None = None,
 | ||
|         yaxis_opts_max: int | float | None = None,
 | ||
|     ) -> None:
 | ||
|         """散点图"""
 | ||
| 
 | ||
|         # 根据数据体列数匹配生成散点图方法
 | ||
|         match dataframe.shape[1]:
 | ||
| 
 | ||
|             # 默认为数据行第一个数据为系列名称、第二个数据为X坐标轴值、第三个数据为Y坐标轴值、第四个数据为标记大小
 | ||
|             case 4:
 | ||
| 
 | ||
|                 pass
 | ||
| 
 | ||
|         # 创建散点图(默认初始化配置项)
 | ||
|         chart = Scatter(init_opts=self._init_opts())
 | ||
| 
 | ||
|         chart.set_global_opts(
 | ||
|             # 不显示图例
 | ||
|             legend_opts=self._legend_opts(),
 | ||
|             # 不显示提示框
 | ||
|             tooltip_opts=self._tooltip_opts(),
 | ||
|             # X坐标轴配置项,默认第二个列名作为X坐标轴名称
 | ||
|             xaxis_opts=self._axis_opts(
 | ||
|                 name=dataframe.columns[1], min_=xaxis_opts_min, max_=xaxis_opts_max
 | ||
|             ),
 | ||
|             # Y坐标轴配置项,默认第三个列名作为X坐标轴名称
 | ||
|             yaxis_opts=self._axis_opts(
 | ||
|                 name=dataframe.columns[2], min_=yaxis_opts_min, max_=yaxis_opts_max
 | ||
|             ),
 | ||
|         )
 | ||
| 
 | ||
|         for series_name in dataframe[dataframe.columns[0]].unique():
 | ||
| 
 | ||
|             chart.add_xaxis(
 | ||
|                 xaxis_data=dataframe.loc[
 | ||
|                     dataframe[dataframe.columns[0]] == series_name,
 | ||
|                     dataframe.columns[1],
 | ||
|                 ].tolist()
 | ||
|             )
 | ||
| 
 | ||
|             # noinspection PyTypeChecker
 | ||
|             chart.add_yaxis(
 | ||
|                 # 系列名称
 | ||
|                 series_name=series_name,
 | ||
|                 # 系列数据
 | ||
|                 y_axis=[
 | ||
|                     options.ScatterItem(
 | ||
|                         # 数据项名称
 | ||
|                         name=row.iloc[3],
 | ||
|                         # 数据项值
 | ||
|                         value=[row.iloc[1], row.iloc[2]],
 | ||
|                         # 标记大小,经过MIN-MAX归一化至20~60
 | ||
|                         symbol_size=20
 | ||
|                         + 40
 | ||
|                         * (row.iloc[3] - dataframe[dataframe.columns[3]].min())
 | ||
|                         / (
 | ||
|                             dataframe[dataframe.columns[3]].max()
 | ||
|                             - dataframe[dataframe.columns[3]].min()
 | ||
|                         ),
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self._label_opts(
 | ||
|                             # 标签的位置
 | ||
|                             position="right",
 | ||
|                             # 标签内容格式器,在散点图中:{a}(系列名称),{b}(数据名称),{c}(数值数组)
 | ||
|                             formatter="{a|{a}}\n{b|{b}}",
 | ||
|                             # 文字块富文本样式
 | ||
|                             rich={
 | ||
|                                 "a": {"fontWeight": "bold"},
 | ||
|                                 "b": {"lineHeight": 25},
 | ||
|                             },
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     for _, row in dataframe[
 | ||
|                         dataframe[dataframe.columns[0]] == series_name
 | ||
|                     ].iterrows()
 | ||
|                 ],  # 使用散点图数据项设置系列数据
 | ||
|             )
 | ||
| 
 | ||
|         chart.render(file_name)
 | ||
| 
 | ||
|     def bar(
 | ||
|         self, dataframe: pandas.DataFrame, file_name: str, stack: bool = False
 | ||
|     ) -> None:
 | ||
|         """柱状图"""
 | ||
| 
 | ||
|         # 创建柱状图(默认初始化配置项)
 | ||
|         chart = Bar(init_opts=self._init_opts())
 | ||
| 
 | ||
|         chart.set_global_opts(
 | ||
|             # 显示图例
 | ||
|             legend_opts=self._legend_opts(is_show=True if stack else False),
 | ||
|             # 不显示提示框
 | ||
|             tooltip_opts=self._tooltip_opts(),
 | ||
|             # X坐标轴配置项,默认第二个列名作为X坐标轴名称
 | ||
|             xaxis_opts=self._axis_opts(
 | ||
|                 type_="category", name=dataframe.columns[1], axislabel_rotate=-30
 | ||
|             ),
 | ||
|             # Y坐标轴配置项,默认第三个列名作为Y坐标轴名称
 | ||
|             yaxis_opts=self._axis_opts(
 | ||
|                 name=dataframe.columns[2],
 | ||
|             ),
 | ||
|         )
 | ||
| 
 | ||
|         chart.add_xaxis(
 | ||
|             xaxis_data=dataframe[dataframe.columns[1]].unique().tolist()
 | ||
|         )  # 柱状图和散点图在新增X坐标轴方法不相同
 | ||
| 
 | ||
|         for series_name in dataframe[dataframe.columns[0]].unique():
 | ||
| 
 | ||
|             # noinspection PyTypeChecker
 | ||
|             chart.add_yaxis(
 | ||
|                 # 系列名称
 | ||
|                 series_name=series_name,
 | ||
|                 # 系列数据
 | ||
|                 y_axis=[
 | ||
|                     options.BarItem(
 | ||
|                         # 数据项名称
 | ||
|                         name=None,
 | ||
|                         # 数据项值
 | ||
|                         value=[row.iloc[1], row.iloc[2]],
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self._label_opts(
 | ||
|                             # 标签内容格式器,在柱状图中:{a}(系列名称),{b}(数据名称),{c}(数值数组)
 | ||
|                             # 显示数据项值的第二个值
 | ||
|                             formatter="{value|{@[1]}}",
 | ||
|                             # 文字块富文本样式
 | ||
|                             rich={
 | ||
|                                 "value": {"fontWeight": "bold"},
 | ||
|                             },
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     for _, row in dataframe[
 | ||
|                         dataframe[dataframe.columns[0]] == series_name
 | ||
|                     ].iterrows()
 | ||
|                 ],  # 使用散点图数据项设置系列数据
 | ||
|                 # 数据堆叠
 | ||
|                 stack="bar_stacked" if stack else None,
 | ||
|             )
 | ||
| 
 | ||
|         chart.render(file_name)
 | ||
| 
 | ||
|     def line(
 | ||
|         self,
 | ||
|         dataframe: pandas.DataFrame,
 | ||
|         file_name: str,
 | ||
|         yaxis_opts_min: int | float | None = None,
 | ||
|         yaxis_opts_max: int | float | None = None,
 | ||
|     ) -> None:
 | ||
|         """折线图"""
 | ||
| 
 | ||
|         # 创建折线图(默认初始化配置项)
 | ||
|         chart = Line(init_opts=self._init_opts())
 | ||
| 
 | ||
|         chart.set_global_opts(
 | ||
|             # 不显示图例
 | ||
|             legend_opts=self._legend_opts(is_show=True),
 | ||
|             # 不显示提示框
 | ||
|             tooltip_opts=self._tooltip_opts(),
 | ||
|             # X坐标轴配置项,默认第二个列名作为X坐标轴名称
 | ||
|             xaxis_opts=self._axis_opts(
 | ||
|                 type_="category",
 | ||
|                 name=dataframe.columns[1],
 | ||
|                 boundary_gap=False,
 | ||
|                 axislabel_rotate=-30,
 | ||
|             ),
 | ||
|             # Y坐标轴配置项,默认第三个列名作为Y坐标轴名称
 | ||
|             yaxis_opts=self._axis_opts(
 | ||
|                 name=dataframe.columns[2],
 | ||
|                 min_=yaxis_opts_min,
 | ||
|                 max_=yaxis_opts_max,
 | ||
|             ),
 | ||
|         )
 | ||
| 
 | ||
|         chart.add_xaxis(xaxis_data=dataframe[dataframe.columns[1]].unique().tolist())
 | ||
| 
 | ||
|         for series_name in dataframe[dataframe.columns[0]].unique():
 | ||
| 
 | ||
|             # noinspection PyTypeChecker
 | ||
|             chart.add_yaxis(
 | ||
|                 series_name=series_name,
 | ||
|                 # 系列数据
 | ||
|                 y_axis=[
 | ||
|                     options.LineItem(
 | ||
|                         # 数据项值
 | ||
|                         value=[row.iloc[1], row.iloc[2]],
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self._label_opts(
 | ||
|                             # 标签的位置
 | ||
|                             position="right",
 | ||
|                             # 标签内容格式器,在折线图中:{a}(系列名称),{b}(数据名称),{c}(数值数组)
 | ||
|                             # 显示数据项值的第二个值
 | ||
|                             formatter="{value|{@[1]}}",
 | ||
|                             # 文字块富文本样式
 | ||
|                             rich={
 | ||
|                                 "value": {"fontWeight": "bold"},
 | ||
|                             },
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     for _, row in dataframe[
 | ||
|                         dataframe[dataframe.columns[0]] == series_name
 | ||
|                     ].iterrows()
 | ||
|                 ],  # 使用折线图数据项设置系列数据
 | ||
|                 # 是否平滑曲线
 | ||
|                 is_smooth=True,
 | ||
|                 # 线样式配置项,默认线宽为2.5、线的颜色为跟随系列颜色
 | ||
|                 linestyle_opts=self._linestyle_opts(width=2.5, color=None),
 | ||
|             )
 | ||
| 
 | ||
|         chart.render(file_name)
 | ||
| 
 | ||
|     def area(
 | ||
|         self,
 | ||
|         dataframe: pandas.DataFrame,
 | ||
|         file_name: str,
 | ||
|         yaxis_opts_min: int | float | None = None,
 | ||
|         yaxis_opts_max: int | float | None = None,
 | ||
|     ) -> None:
 | ||
|         """面积图"""
 | ||
| 
 | ||
|         # 创建面积图(默认初始化配置项)
 | ||
|         chart = Line(init_opts=self._init_opts())
 | ||
| 
 | ||
|         chart.set_global_opts(
 | ||
|             # 不显示图例
 | ||
|             legend_opts=self._legend_opts(),
 | ||
|             # 不显示提示框
 | ||
|             tooltip_opts=self._tooltip_opts(),
 | ||
|             # X坐标轴配置项,默认第一个列名作为X坐标轴名称
 | ||
|             xaxis_opts=self._axis_opts(
 | ||
|                 type_="category",
 | ||
|                 name=dataframe.columns[0],
 | ||
|                 boundary_gap=False,
 | ||
|                 axislabel_rotate=-30,
 | ||
|             ),
 | ||
|             # Y坐标轴配置项,默认第二个列名作为Y坐标轴名称
 | ||
|             yaxis_opts=self._axis_opts(
 | ||
|                 name=dataframe.columns[1],
 | ||
|                 min_=yaxis_opts_min,
 | ||
|                 max_=yaxis_opts_max,
 | ||
|             ),
 | ||
|         )
 | ||
| 
 | ||
|         chart.add_xaxis(xaxis_data=dataframe[dataframe.columns[0]].tolist())
 | ||
| 
 | ||
|         # noinspection PyTypeChecker
 | ||
|         chart.add_yaxis(
 | ||
|             series_name="series_name",
 | ||
|             # 系列数据
 | ||
|             y_axis=[
 | ||
|                 options.LineItem(
 | ||
|                     # 数据项值
 | ||
|                     value=[row.iloc[0], row.iloc[1]],
 | ||
|                     # 标签配置项
 | ||
|                     label_opts=self._label_opts(
 | ||
|                         # 标签的位置
 | ||
|                         position="right",
 | ||
|                         # 标签内容格式器,在折线图中:{a}(系列名称),{b}(数据名称),{c}(数值数组)
 | ||
|                         # 显示数据项值的第二个值
 | ||
|                         formatter="{value|{@[1]}}",
 | ||
|                         # 文字块富文本样式
 | ||
|                         rich={
 | ||
|                             "value": {"fontWeight": "bold"},
 | ||
|                         },
 | ||
|                     ),
 | ||
|                 )
 | ||
|                 for _, row in dataframe.iterrows()
 | ||
|             ],  # 使用折线图数据项设置系列数据
 | ||
|             # 是否平滑曲线
 | ||
|             is_smooth=True,
 | ||
|             # 线样式配置项,默认线宽为2.5、线的颜色为跟随系列颜色
 | ||
|             linestyle_opts=self._linestyle_opts(width=2.5, color=None),
 | ||
|             # 填充区域配置项
 | ||
|             areastyle_opts=self._areastyle_opts(),
 | ||
|         )
 | ||
| 
 | ||
|         chart.render(file_name)
 | ||
| 
 | ||
|     # 基本图表
 | ||
| 
 | ||
|     def pie(
 | ||
|         self,
 | ||
|         dataframe: pandas.DataFrame,
 | ||
|         file_name: str,
 | ||
|         rosetype: str | None = "area",
 | ||
|     ) -> None:
 | ||
|         """饼图"""
 | ||
| 
 | ||
|         # 创建饼图(默认初始化配置项)
 | ||
|         chart = Pie(init_opts=self._init_opts())
 | ||
| 
 | ||
|         chart.set_global_opts(
 | ||
|             # 不显示图例
 | ||
|             legend_opts=self._legend_opts(),
 | ||
|             # 不显示提示框
 | ||
|             tooltip_opts=self._tooltip_opts(),
 | ||
|         )
 | ||
| 
 | ||
|         chart.add(
 | ||
|             # 系列名称,默认为第一个列名
 | ||
|             series_name=dataframe.columns.tolist()[0],
 | ||
|             # 系列数据项,默认为数据行前两个数据
 | ||
|             data_pair=[[row.iloc[0], row.iloc[1]] for _, row in dataframe.iterrows()],
 | ||
|             # 是否展示成南丁格尔图,玫瑰图,扇区圆心角相同,通过半径区分组数据大小
 | ||
|             # area:所有扇区圆心角相同,通过半径展现数据大小
 | ||
|             # radius:扇区圆心角展现数据的百分比,半径展现数据的大小
 | ||
|             # None:不展示成南丁格尔图(饼图)
 | ||
|             rosetype=rosetype,
 | ||
|             # 中心坐标
 | ||
|             center=["50%", "60%"],
 | ||
|             # 饼图的扇区顺时针排布
 | ||
|             is_clockwise=True,
 | ||
|             # 标签配置项
 | ||
|             label_opts=self._label_opts(
 | ||
|                 # 标签的位置默认为外部
 | ||
|                 position="outside",
 | ||
|                 # 标签内容格式器,在饼图中:{a}系列名称,{b}数据项名称,{c}数值,{d}百分比
 | ||
|                 formatter="{b|{b}}\n{c|{c}}",
 | ||
|                 # 文字块富文本样式
 | ||
|                 rich={"b": {"fontWeight": "bold"}, "c": {"lineHeight": 25}},
 | ||
|             ),
 | ||
|         )
 | ||
| 
 | ||
|         chart.render(file_name)
 | ||
| 
 | ||
|     # 全局配置项(先总再分,先全局再系列)
 | ||
| 
 | ||
|     # 初始化配置项
 | ||
|     def _init_opts(
 | ||
|         self,
 | ||
|         # 图表画布宽度
 | ||
|         width="500px",
 | ||
|         # 图表画布高度
 | ||
|         height="350px",
 | ||
|         # 图表主题
 | ||
|         theme=ThemeType.WALDEN,
 | ||
|         # 网页标题,默认为全局网页标题
 | ||
|         page_title=CurrentConfig.PAGE_TITLE,
 | ||
|         # 图表动画初始化配置
 | ||
|         animation_opts=None,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若图表动画初始化配置为空则为默认配置
 | ||
|         if not animation_opts:
 | ||
| 
 | ||
|             animation_opts = self._animation_opts()
 | ||
| 
 | ||
|         return options.InitOpts(
 | ||
|             width=width,
 | ||
|             height=height,
 | ||
|             theme=theme,
 | ||
|             page_title=page_title,
 | ||
|             animation_opts=animation_opts,
 | ||
|         )
 | ||
| 
 | ||
|     # 图表动画初始化配置
 | ||
|     @staticmethod
 | ||
|     def _animation_opts(
 | ||
|         # 是否开启动画
 | ||
|         animation=False,
 | ||
|     ):
 | ||
| 
 | ||
|         return options.AnimationOpts(animation=animation)
 | ||
| 
 | ||
|     # 图例配置项
 | ||
|     def _legend_opts(
 | ||
|         self,
 | ||
|         # 图例字体样式,默认为中黑、常规、12像素
 | ||
|         textstyle_opts=None,
 | ||
|         # 是否显示图例,默认为不显示
 | ||
|         is_show=False,
 | ||
|         # 组件距离容器左侧位置,默认为居中
 | ||
|         pos_left="center",
 | ||
|         # 组件距离容器上侧位置,默认为上侧
 | ||
|         pos_top="top",
 | ||
|         # 组件布局朝向,默认为水平
 | ||
|         orient="horizontal",
 | ||
|         # 组件对齐方式,默认为自动
 | ||
|         align="auto",
 | ||
|         # 组件内边距,默认为5
 | ||
|         padding=5,
 | ||
|         # 图例标记的图形宽度,默认为10
 | ||
|         item_width=10,
 | ||
|         # 图例标记的图形高度,默认为10
 | ||
|         item_height=10,
 | ||
|         # 图例关闭时的颜色,默认为中黑
 | ||
|         inactive_color="#86909C",
 | ||
|         # 图例的边框线宽
 | ||
|         border_width=0,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若文字样式配置项为空则为默认配置
 | ||
|         if not textstyle_opts:
 | ||
| 
 | ||
|             textstyle_opts = self._textstyle_opts()
 | ||
| 
 | ||
|         return options.LegendOpts(
 | ||
|             textstyle_opts=textstyle_opts,
 | ||
|             is_show=is_show,
 | ||
|             pos_left=pos_left,
 | ||
|             pos_top=pos_top,
 | ||
|             orient=orient,
 | ||
|             align=align,
 | ||
|             padding=padding,
 | ||
|             item_width=item_width,
 | ||
|             item_height=item_height,
 | ||
|             inactive_color=inactive_color,
 | ||
|             border_width=border_width,
 | ||
|         )
 | ||
| 
 | ||
|     # 提示框配置项
 | ||
|     @staticmethod
 | ||
|     def _tooltip_opts(
 | ||
|         # 是否显示提示框,默认为不显示
 | ||
|         is_show=False,
 | ||
|     ):
 | ||
| 
 | ||
|         return options.TooltipOpts(is_show=is_show)
 | ||
| 
 | ||
|     # 标题配置项
 | ||
|     def _title_opts(
 | ||
|         self,
 | ||
|         # 标题的文字样式,默认为黑、加粗、20
 | ||
|         title_textstyle_opts=None,
 | ||
|         # 副标题的文字样式,默认为中黑、常规、14
 | ||
|         subtitle_textstyle_opts=None,
 | ||
|         # 否显示标题,默认为不显示
 | ||
|         is_show=False,
 | ||
|         # 标题的文本,默认为空
 | ||
|         title=None,
 | ||
|         # 副标题的文本,默认为空
 | ||
|         subtitle=None,
 | ||
|         # 组件距离容器左侧位置,默认为左侧
 | ||
|         pos_left="left",
 | ||
|         # 组件距离容器上侧位置,默认为上侧
 | ||
|         pos_top="top",
 | ||
|         # 组件内边距,默认为[上0、右0、下0、左60]
 | ||
|         padding=None,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若标题的文字样式配置项为空则为默认配置
 | ||
|         if not title_textstyle_opts:
 | ||
| 
 | ||
|             title_textstyle_opts = self._textstyle_opts(
 | ||
|                 color="#1D2129", font_weight="bold", font_size=20
 | ||
|             )
 | ||
| 
 | ||
|         # 若标题的文字样式配置项为空则为默认配置
 | ||
|         if not subtitle_textstyle_opts:
 | ||
| 
 | ||
|             subtitle_textstyle_opts = self._textstyle_opts(font_size=14)
 | ||
| 
 | ||
|         # 若组件内边距为空则为默认配置
 | ||
|         if not padding:
 | ||
| 
 | ||
|             padding = [0, 0, 0, 60]
 | ||
| 
 | ||
|         return options.TitleOpts(
 | ||
|             title_textstyle_opts=title_textstyle_opts,
 | ||
|             subtitle_textstyle_opts=subtitle_textstyle_opts,
 | ||
|             is_show=is_show,
 | ||
|             title=title,
 | ||
|             subtitle=subtitle,
 | ||
|             pos_left=pos_left,
 | ||
|             pos_top=pos_top,
 | ||
|             padding=padding,
 | ||
|         )
 | ||
| 
 | ||
|     # 坐标轴配置项
 | ||
|     def _axis_opts(
 | ||
|         self,
 | ||
|         # 坐标轴轴线配置项,默认为中黑
 | ||
|         axisline_opts=None,
 | ||
|         # 坐标轴刻度配置项,默认为中黑
 | ||
|         axistick_opts=None,
 | ||
|         # 坐标轴标签配置项-标签旋转
 | ||
|         axislabel_rotate=None,
 | ||
|         # 坐标轴名称文字样式,默认为中黑、常规、12像素
 | ||
|         name_textstyle_opts=None,
 | ||
|         # 分割线配置项,默认为不显示
 | ||
|         splitline_opts=None,
 | ||
|         # 坐标轴类型,默认为数值轴,可选CATEGORY类目轴、TIME时间轴
 | ||
|         type_="value",
 | ||
|         # 坐标轴名称,默认为空
 | ||
|         name=None,
 | ||
|         # 是否显示坐标轴,默认为显示
 | ||
|         is_show=True,
 | ||
|         # 坐标轴名称与轴线之间的距离,默认为15
 | ||
|         name_gap=15,
 | ||
|         # 强制设置坐标轴分割间隔
 | ||
|         interval=None,
 | ||
|         # 坐标轴的分割段数,默认为5
 | ||
|         split_number=5,
 | ||
|         # 坐标轴两边留白策略
 | ||
|         boundary_gap=None,
 | ||
|         # 坐标轴刻度最小值
 | ||
|         min_=None,
 | ||
|         # 坐标轴刻度最大值
 | ||
|         max_=None,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若坐标轴轴线配置项为空则为默认配置
 | ||
|         if not axisline_opts:
 | ||
| 
 | ||
|             axisline_opts = self._axisline_opts()
 | ||
| 
 | ||
|         # 若坐标轴刻度配置项为空则为默认配置
 | ||
|         if not axistick_opts:
 | ||
| 
 | ||
|             axistick_opts = self._axistick_opts()
 | ||
| 
 | ||
|         # 若坐标轴名称文字样式为空则为默认配置
 | ||
|         if not name_textstyle_opts:
 | ||
| 
 | ||
|             name_textstyle_opts = self._textstyle_opts()
 | ||
| 
 | ||
|         if not splitline_opts:
 | ||
| 
 | ||
|             splitline_opts = self._splitline_opts()
 | ||
| 
 | ||
|         return options.AxisOpts(
 | ||
|             axisline_opts=axisline_opts,
 | ||
|             axistick_opts=axistick_opts,
 | ||
|             name_textstyle_opts=name_textstyle_opts,
 | ||
|             splitline_opts=splitline_opts,
 | ||
|             type_=type_,
 | ||
|             name=name,
 | ||
|             is_show=is_show,
 | ||
|             name_gap=name_gap,
 | ||
|             interval=interval,
 | ||
|             split_number=split_number,
 | ||
|             boundary_gap=boundary_gap,
 | ||
|             min_=min_,
 | ||
|             max_=max_,
 | ||
|             axislabel_opts=self._label_opts(rotate=axislabel_rotate),
 | ||
|         )
 | ||
| 
 | ||
|     # 坐标轴轴线配置项
 | ||
|     def _axisline_opts(
 | ||
|         self,
 | ||
|         # 是否显示轴线,默认显示
 | ||
|         is_show=True,
 | ||
|         # 线样式配置项,默认为中黑
 | ||
|         linestyle_opts=None,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若线样式配置项为空则为默认配置
 | ||
|         if not linestyle_opts:
 | ||
| 
 | ||
|             linestyle_opts = self._linestyle_opts()
 | ||
| 
 | ||
|         return options.AxisLineOpts(is_show=is_show, linestyle_opts=linestyle_opts)
 | ||
| 
 | ||
|     # 坐标轴刻度配置项
 | ||
|     def _axistick_opts(
 | ||
|         self,
 | ||
|         # 是否显示坐标轴刻度,默认为否
 | ||
|         is_show=False,
 | ||
|         # 线样式配置项,默认为中黑
 | ||
|         linestyle_opts=None,
 | ||
|         # 坐标轴刻度是否朝内,默认为朝内
 | ||
|         is_inside=True,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若线样式配置项为空则为默认配置
 | ||
|         if not linestyle_opts:
 | ||
| 
 | ||
|             linestyle_opts = self._linestyle_opts()
 | ||
| 
 | ||
|         return options.AxisTickOpts(
 | ||
|             is_show=is_show, is_inside=is_inside, linestyle_opts=linestyle_opts
 | ||
|         )
 | ||
| 
 | ||
|     # 视觉映射配置项
 | ||
|     def _visualmap_opts(
 | ||
|         self,
 | ||
|         # 指定visualMapPiecewise组件的最大值
 | ||
|         max_=1,
 | ||
|         # 如何放置visualMap组件
 | ||
|         orient="horizontal",
 | ||
|         # visualMap组件离容器左侧的距离
 | ||
|         pos_left="center",
 | ||
|         # visualMap组件离容器上侧的距离
 | ||
|         pos_top="top",
 | ||
|         # 数据展示的小数精度
 | ||
|         precision=2,
 | ||
|         # 文字样式配置项
 | ||
|         textstyle_opts=None,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若文字样式配置项为空则为默认配置
 | ||
|         if not textstyle_opts:
 | ||
| 
 | ||
|             textstyle_opts = self._textstyle_opts()
 | ||
| 
 | ||
|         return options.VisualMapOpts(
 | ||
|             max_=max_,
 | ||
|             orient=orient,
 | ||
|             pos_left=pos_left,
 | ||
|             pos_top=pos_top,
 | ||
|             precision=precision,
 | ||
|             textstyle_opts=textstyle_opts,
 | ||
|         )
 | ||
| 
 | ||
|     # 系列配置项
 | ||
| 
 | ||
|     # 图元样式配置项
 | ||
|     @staticmethod
 | ||
|     def _itemstyle_opts(
 | ||
|         # 图形透明度
 | ||
|         opacity=0.2,
 | ||
|     ):
 | ||
| 
 | ||
|         return options.ItemStyleOpts(opacity=opacity)
 | ||
| 
 | ||
|     # 文本样式配置项
 | ||
|     @staticmethod
 | ||
|     def _textstyle_opts(
 | ||
|         # 文字颜色,默认为中黑
 | ||
|         color="#86909C",
 | ||
|         # 文字字体的风格,默认为常规
 | ||
|         font_style="normal",
 | ||
|         # 文字字体的粗细,默认为常规
 | ||
|         font_weight="normal",
 | ||
|         # 文字字体的系列,默认为苹方
 | ||
|         font_family="PingFang SC",
 | ||
|         # 文字字体的大小,默认为12
 | ||
|         font_size=12,
 | ||
|     ):
 | ||
| 
 | ||
|         return options.TextStyleOpts(
 | ||
|             color=color,
 | ||
|             font_style=font_style,
 | ||
|             font_weight=font_weight,
 | ||
|             font_family=font_family,
 | ||
|             font_size=font_size,
 | ||
|         )
 | ||
| 
 | ||
|     # 标签配置项
 | ||
|     @staticmethod
 | ||
|     def _label_opts(
 | ||
|         # 是否显示标签
 | ||
|         is_show=True,
 | ||
|         # 标签的位置
 | ||
|         position="inside",
 | ||
|         # 文字的颜色,默认为中黑
 | ||
|         color="#86909C",
 | ||
|         # 文字的字体大小,默认为12
 | ||
|         font_size=12,
 | ||
|         # 文字的字体粗细,默认为常规
 | ||
|         font_weight="normal",
 | ||
|         # 文字的字体系列,默认为苹方
 | ||
|         font_family="PingFang SC",
 | ||
|         # 标签旋转
 | ||
|         rotate=None,
 | ||
|         # 标签内容格式器,默认为空
 | ||
|         formatter=None,
 | ||
|         # 文字块背景色,默认为无
 | ||
|         background_color=None,
 | ||
|         # 文字块边框颜色
 | ||
|         border_color=None,
 | ||
|         # 文字块边框宽度
 | ||
|         border_width=None,
 | ||
|         # 文字块圆角
 | ||
|         border_radius=None,
 | ||
|         # 文字块富文本样式
 | ||
|         rich=None,
 | ||
|     ):
 | ||
| 
 | ||
|         return options.LabelOpts(
 | ||
|             is_show=is_show,
 | ||
|             position=position,
 | ||
|             color=color,
 | ||
|             font_size=font_size,
 | ||
|             font_weight=font_weight,
 | ||
|             font_family=font_family,
 | ||
|             rotate=rotate,
 | ||
|             formatter=formatter,
 | ||
|             background_color=background_color,
 | ||
|             border_color=border_color,
 | ||
|             border_width=border_width,
 | ||
|             border_radius=border_radius,
 | ||
|             rich=rich,
 | ||
|         )
 | ||
| 
 | ||
|     # 线样式配置项
 | ||
|     @staticmethod
 | ||
|     def _linestyle_opts(
 | ||
|         # 线宽,默认为1
 | ||
|         width=1,
 | ||
|         # 线的类型,默认为实线
 | ||
|         type_="solid",
 | ||
|         # 线的颜色,默认为中黑
 | ||
|         color="#86909C",
 | ||
|     ):
 | ||
| 
 | ||
|         return options.LineStyleOpts(width=width, type_=type_, color=color)
 | ||
| 
 | ||
|     # 分割线配置项
 | ||
|     def _splitline_opts(
 | ||
|         self,
 | ||
|         # 线样式配置项,默认为虚线、浅黑
 | ||
|         linestyle_opts=None,
 | ||
|         # 是否显示分割线,默认为不显示
 | ||
|         is_show=False,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若线样式配置项为空则为默认配置
 | ||
|         if not linestyle_opts:
 | ||
|             # 线样式配置项,默认为虚线、浅黑
 | ||
|             linestyle_opts = self._linestyle_opts(type_="dashed", color="#E5E6EB")
 | ||
| 
 | ||
|         return options.SplitLineOpts(is_show=is_show, linestyle_opts=linestyle_opts)
 | ||
| 
 | ||
|     # 标记线配置项
 | ||
|     def _markline_opts(
 | ||
|         self,
 | ||
|         # 标记线数据
 | ||
|         data,
 | ||
|         # 响应和触发鼠标事件,默认为不响应
 | ||
|         is_silent=False,
 | ||
|         # 标签配置项
 | ||
|         label_opts=None,
 | ||
|         # 线样式配置项
 | ||
|         linestyle_opts=None,
 | ||
|     ):
 | ||
| 
 | ||
|         # 若标签配置项为空则默认配置
 | ||
|         if not label_opts:
 | ||
| 
 | ||
|             label_opts = self._label_opts()
 | ||
| 
 | ||
|         # 线样式配置项为空则默认配置
 | ||
|         if not linestyle_opts:
 | ||
|             # 线样式配置项,默认为虚线、浅黑
 | ||
|             linestyle_opts = self._linestyle_opts(type_="dashed", color="#E5E6EB")
 | ||
| 
 | ||
|         return options.MarkLineOpts(
 | ||
|             is_silent=is_silent,
 | ||
|             data=data,
 | ||
|             label_opts=label_opts,
 | ||
|             linestyle_opts=linestyle_opts,
 | ||
|         )
 | ||
| 
 | ||
|     # 区域填充样式配置项
 | ||
|     @staticmethod
 | ||
|     def _areastyle_opts(
 | ||
|         # 图形透明度(0为透明,1为不透明),默认为0.2
 | ||
|         opacity=0.2,
 | ||
|     ):
 | ||
| 
 | ||
|         return options.AreaStyleOpts(opacity)
 | ||
| 
 | ||
| 
 | ||
| """
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             # 条柱和折线图,左侧为条柱图纵坐标,右侧为折线图纵坐标
 | ||
|             case "bar+line":
 | ||
| 
 | ||
|                 # 先生成柱状图再叠加折线图
 | ||
| 
 | ||
|                 bar = (
 | ||
|                     Bar(init_opts=self._init_opts())
 | ||
|                     .set_global_opts(
 | ||
|                         # 显示图例
 | ||
|                         legend_opts=self.LegendOpts(is_show=True),
 | ||
|                         # 不显示提示框
 | ||
|                         tooltip_opts=self.TooltipOpts(),
 | ||
|                         # X轴配置项
 | ||
|                         xaxis_opts=self.AxisOpts(
 | ||
|                             # 以第一个列名作为坐标轴名称
 | ||
|                             name=dataframe.columns[0],
 | ||
|                             # 坐标轴轴线配置项
 | ||
|                             axisline_opts=self.AxisLineOpts(),
 | ||
|                             # 显示刻线
 | ||
|                             axistick_opts=self.AxisTickOpts(is_show=True),
 | ||
|                             # 不显示分割线
 | ||
|                             splitline_opts=self.SplitLineOpts(),
 | ||
|                             # 坐标轴名称配置项,加粗、14像素
 | ||
|                             name_textstyle_opts=self.TextStyleOpts(
 | ||
|                                 font_weight="bold", font_size="14px"
 | ||
|                             ),
 | ||
|                             # 坐标轴标签配置项
 | ||
|                             axislabel_opts=self.LabelOpts(
 | ||
|                                 # 标签旋转30度(逆时针)
 | ||
|                                 rotate=30
 | ||
|                             ),
 | ||
|                         ),
 | ||
|                         # 不显示轴线
 | ||
|                         yaxis_opts=self.AxisOpts(
 | ||
|                             # 不显示坐标轴
 | ||
|                             is_show=False
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     # 第一列作为X轴
 | ||
|                     .add_xaxis(
 | ||
|                         # 将X轴数值转为字符
 | ||
|                         xaxis_data=dataframe[dataframe.columns[0]]
 | ||
|                         .astype("str")
 | ||
|                         .tolist()
 | ||
|                     )
 | ||
|                     # 第二列作为左侧Y轴
 | ||
|                     .add_yaxis(
 | ||
|                         # 系列名称
 | ||
|                         series_name=dataframe.columns[1],
 | ||
|                         # Y轴数据
 | ||
|                         y_axis=dataframe[dataframe.columns[1]].tolist(),
 | ||
|                         # 使用的Y轴的索引,存在多个Y轴的时候有用
 | ||
|                         yaxis_index=0,
 | ||
|                         # 系列颜色
 | ||
|                         color="#165DFF",
 | ||
|                         # 同一系列的柱间距离
 | ||
|                         category_gap="35%",
 | ||
|                         # 不同系列的柱间距离
 | ||
|                         gap="15%",
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self.LabelOpts(
 | ||
|                             # 标签位置,左侧
 | ||
|                             position="left",
 | ||
|                             # 文字字体的粗细,加粗
 | ||
|                             font_weight="bold",
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     .extend_axis(
 | ||
|                         yaxis=self.AxisOpts(
 | ||
|                             # 不显示坐标轴
 | ||
|                             is_show=False
 | ||
|                         )
 | ||
|                     )
 | ||
|                 )
 | ||
| 
 | ||
|                 line = (
 | ||
|                     Line(init_opts=self._init_opts()).add_xaxis(
 | ||
|                         xaxis_data=dataframe[dataframe.columns[0]]
 | ||
|                         .astype("str")
 | ||
|                         .tolist()
 | ||
|                     )
 | ||
|                     # 第三列作为右侧Y轴
 | ||
|                     .add_yaxis(
 | ||
|                         series_name=dataframe.columns[-1],
 | ||
|                         y_axis=dataframe[dataframe.columns[-1]].tolist(),
 | ||
|                         yaxis_index=1,
 | ||
|                         # 系列颜色,碧涛青
 | ||
|                         color="#14C9C9",
 | ||
|                         # 标记的图形
 | ||
|                         symbol="circle",
 | ||
|                         # 标记的大小
 | ||
|                         symbol_size=6,
 | ||
|                         # 是否平滑曲线
 | ||
|                         is_smooth=True,
 | ||
|                         # 折线图在柱状图上
 | ||
|                         z_level=1,
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self.LabelOpts(
 | ||
|                             # 标签位置,顶部
 | ||
|                             position="top",
 | ||
|                             # 文字字体的粗细,加粗
 | ||
|                             font_weight="bold",
 | ||
|                         ),
 | ||
|                     )
 | ||
|                 )
 | ||
| 
 | ||
|                 bar.overlap(line).render(path)
 | ||
| 
 | ||
|             # 双折线图
 | ||
|             case "line+line":
 | ||
| 
 | ||
|                 # 先生成左侧折线图再叠加右侧折线图
 | ||
| 
 | ||
|                 line_left = (
 | ||
|                     Line(init_opts=self._init_opts())
 | ||
|                     .set_global_opts(
 | ||
|                         # 显示图例
 | ||
|                         legend_opts=self.LegendOpts(is_show=True),
 | ||
|                         # 不显示提示框
 | ||
|                         tooltip_opts=self.TooltipOpts(),
 | ||
|                         # X轴配置项
 | ||
|                         xaxis_opts=self.AxisOpts(
 | ||
|                             # 以第一个列名作为坐标轴名称
 | ||
|                             name=dataframe.columns[0],
 | ||
|                             # 坐标轴轴线配置项
 | ||
|                             axisline_opts=self.AxisLineOpts(),
 | ||
|                             # 显示刻线
 | ||
|                             axistick_opts=self.AxisTickOpts(is_show=True),
 | ||
|                             # 不显示分割线
 | ||
|                             splitline_opts=self.SplitLineOpts(),
 | ||
|                             # 坐标轴名称配置项,加粗、14像素
 | ||
|                             name_textstyle_opts=self.TextStyleOpts(
 | ||
|                                 font_weight="bold", font_size="14px"
 | ||
|                             ),
 | ||
|                             # 坐标轴标签配置项
 | ||
|                             axislabel_opts=self.LabelOpts(
 | ||
|                                 # 标签旋转30度(逆时针)
 | ||
|                                 rotate=30
 | ||
|                             ),
 | ||
|                         ),
 | ||
|                         # 不显示轴线
 | ||
|                         yaxis_opts=self.AxisOpts(
 | ||
|                             # 不显示坐标轴
 | ||
|                             is_show=False
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     # 第一列作为X轴
 | ||
|                     .add_xaxis(
 | ||
|                         # 将X轴数值转为字符
 | ||
|                         xaxis_data=dataframe[dataframe.columns[0]]
 | ||
|                         .astype("str")
 | ||
|                         .tolist()
 | ||
|                     )
 | ||
|                     # 第二列作为左侧Y轴
 | ||
|                     .add_yaxis(
 | ||
|                         # 系列名称
 | ||
|                         series_name=dataframe.columns[1],
 | ||
|                         y_axis=dataframe[dataframe.columns[1]].tolist(),
 | ||
|                         # 使用的Y轴的索引,存在多个Y轴的时候有用
 | ||
|                         yaxis_index=0,
 | ||
|                         # 系列颜色
 | ||
|                         color="#165DFF",
 | ||
|                         # 标记的图形
 | ||
|                         symbol="circle",
 | ||
|                         # 标记的大小
 | ||
|                         symbol_size=6,
 | ||
|                         # 是否平滑曲线
 | ||
|                         is_smooth=True,
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self.LabelOpts(
 | ||
|                             # 标签位置,左侧
 | ||
|                             position="left",
 | ||
|                             # 文字字体的粗细,加粗
 | ||
|                             font_weight="bold",
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     .extend_axis(
 | ||
|                         yaxis=self.AxisOpts(
 | ||
|                             # 不显示坐标轴
 | ||
|                             is_show=False
 | ||
|                         )
 | ||
|                     )
 | ||
|                 )
 | ||
| 
 | ||
|                 line_right = (
 | ||
|                     Line(init_opts=self._init_opts()).add_xaxis(
 | ||
|                         xaxis_data=dataframe[dataframe.columns[0]]
 | ||
|                         .astype("str")
 | ||
|                         .tolist()
 | ||
|                     )
 | ||
|                     # 第三列作为右侧Y轴
 | ||
|                     .add_yaxis(
 | ||
|                         series_name=dataframe.columns[-1],
 | ||
|                         y_axis=dataframe[dataframe.columns[-1]].tolist(),
 | ||
|                         yaxis_index=1,
 | ||
|                         # 系列颜色,碧涛青
 | ||
|                         color="#14C9C9",
 | ||
|                         # 标记的图形
 | ||
|                         symbol="circle",
 | ||
|                         # 标记的大小
 | ||
|                         symbol_size=6,
 | ||
|                         # 是否平滑曲线
 | ||
|                         is_smooth=True,
 | ||
|                         # 折线图在柱状图上
 | ||
|                         z_level=1,
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self.LabelOpts(
 | ||
|                             # 标签位置,顶部
 | ||
|                             position="top",
 | ||
|                             # 文字字体的粗细,加粗
 | ||
|                             font_weight="bold",
 | ||
|                         ),
 | ||
|                     )
 | ||
|                 )
 | ||
| 
 | ||
|                 line_left.overlap(line_right).render(path)
 | ||
| 
 | ||
|             # 热力图
 | ||
|             case "heatmap":
 | ||
| 
 | ||
|                 chart = (
 | ||
|                     HeatMap(init_opts=self.InitOpts())
 | ||
|                     .set_global_opts(
 | ||
|                         # 不显示图例
 | ||
|                         legend_opts=self.LegendOpts(),
 | ||
|                         # 不显示提示框
 | ||
|                         tooltip_opts=self.TooltipOpts(),
 | ||
|                         # X轴配置项
 | ||
|                         xaxis_opts=self.AxisOpts(
 | ||
|                             # 坐标轴名称
 | ||
|                             name=None,
 | ||
|                             # 坐标轴轴线配置项
 | ||
|                             axisline_opts=self.AxisLineOpts(),
 | ||
|                             # 显示刻线
 | ||
|                             axistick_opts=self.AxisTickOpts(is_show=True),
 | ||
|                             # 不显示分割线
 | ||
|                             splitline_opts=self.SplitLineOpts(),
 | ||
|                             # 坐标轴名称配置项,加粗、14像素
 | ||
|                             name_textstyle_opts=self.TextStyleOpts(
 | ||
|                                 font_weight="bold", font_size="14px"
 | ||
|                             ),
 | ||
|                             # 坐标轴标签配置项
 | ||
|                             axislabel_opts=self.LabelOpts(
 | ||
|                                 # 标签旋转30度(逆时针)
 | ||
|                                 rotate=30
 | ||
|                             ),
 | ||
|                         ),
 | ||
|                         # Y轴配置项
 | ||
|                         yaxis_opts=self.AxisOpts(
 | ||
|                             # 坐标轴名称
 | ||
|                             name=None,
 | ||
|                             # 坐标轴轴线配置项
 | ||
|                             axisline_opts=self.AxisLineOpts(),
 | ||
|                             # 显示刻线
 | ||
|                             axistick_opts=self.AxisTickOpts(is_show=True),
 | ||
|                             # 不显示分割线
 | ||
|                             splitline_opts=self.SplitLineOpts(),
 | ||
|                             # 坐标轴名称配置项,加粗、14像素
 | ||
|                             name_textstyle_opts=self.TextStyleOpts(
 | ||
|                                 font_weight="bold", font_size="14px"
 | ||
|                             ),
 | ||
|                             # 坐标轴标签配置项
 | ||
|                             axislabel_opts=self.LabelOpts(
 | ||
|                                 # 标签旋转30度(逆时针)
 | ||
|                                 rotate=30
 | ||
|                             ),
 | ||
|                         ),
 | ||
|                         visualmap_opts=self.VisualMapOpts(),
 | ||
|                     )
 | ||
|                     .add_xaxis(
 | ||
|                         # 索引作为X轴
 | ||
|                         xaxis_data=dataframe.index.tolist()
 | ||
|                     )
 | ||
|                     .add_yaxis(
 | ||
|                         # 第三个列名作为系列名称
 | ||
|                         series_name=dataframe.columns[2],
 | ||
|                         # 列名作为Y轴
 | ||
|                         yaxis_data=dataframe.columns.tolist(),
 | ||
|                         # 系列数据项
 | ||
|                         value=[
 | ||
|                             [i, j, formatter(dataframe.iloc[i, j])]
 | ||
|                             for i in range(dataframe.shape[0])
 | ||
|                             for j in range(dataframe.shape[1])
 | ||
|                         ],
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self.LabelOpts(
 | ||
|                             # 标签的位置默认为内部
 | ||
|                             position="inside"
 | ||
|                         ),
 | ||
|                     )
 | ||
|                 )
 | ||
| 
 | ||
|                 chart.render(path)
 | ||
| 
 | ||
| 
 | ||
|             # 堆积柱形图
 | ||
|             case "stacked_bar":
 | ||
| 
 | ||
|                 chart = (
 | ||
|                     Bar(init_opts=self._init_opts()).set_global_opts(
 | ||
|                         # 显示图例
 | ||
|                         legend_opts=self.LegendOpts(is_show=True),
 | ||
|                         # 不显示提示框
 | ||
|                         tooltip_opts=self.TooltipOpts(),
 | ||
|                         # X轴配置项
 | ||
|                         xaxis_opts=self.AxisOpts(
 | ||
|                             # 以第一个列名作为坐标轴名称
 | ||
|                             name=None,
 | ||
|                             # 坐标轴轴线配置项
 | ||
|                             axisline_opts=self.AxisLineOpts(),
 | ||
|                             # 显示刻线
 | ||
|                             axistick_opts=self.AxisTickOpts(is_show=True),
 | ||
|                             # 不显示分割线
 | ||
|                             splitline_opts=self.SplitLineOpts(),
 | ||
|                             # 坐标轴名称配置项,加粗、14像素
 | ||
|                             name_textstyle_opts=self.TextStyleOpts(
 | ||
|                                 font_weight="bold", font_size="14px"
 | ||
|                             ),
 | ||
|                             # 坐标轴标签配置项
 | ||
|                             axislabel_opts=self.LabelOpts(
 | ||
|                                 # 标签旋转30度(逆时针)
 | ||
|                                 rotate=30
 | ||
|                             ),
 | ||
|                         ),
 | ||
|                         # 不显示轴线
 | ||
|                         yaxis_opts=self.AxisOpts(
 | ||
|                             # 不显示坐标轴
 | ||
|                             is_show=False
 | ||
|                         ),
 | ||
|                     )
 | ||
|                     # 第一列作为X轴
 | ||
|                     .add_xaxis(
 | ||
|                         # 将X轴数值转为字符
 | ||
|                         xaxis_data=dataframe[dataframe.columns[0]]
 | ||
|                         .astype("str")
 | ||
|                         .tolist()
 | ||
|                     )
 | ||
|                     # 颜色配置项
 | ||
|                     .set_colors(paint(dataframe.shape[1] - 1))
 | ||
|                 )
 | ||
| 
 | ||
|                 for column in dataframe.columns[1:]:
 | ||
| 
 | ||
|                     chart.add_yaxis(
 | ||
|                         # 系列名称
 | ||
|                         series_name=column,
 | ||
|                         # Y轴数据
 | ||
|                         y_axis=dataframe[column].tolist(),
 | ||
|                         stack="stacked_bar",
 | ||
|                         # 同一系列的柱间距离
 | ||
|                         category_gap="35%",
 | ||
|                         # 不同系列的柱间距离
 | ||
|                         gap="15%",
 | ||
|                         # 标签配置项
 | ||
|                         label_opts=self.LabelOpts(
 | ||
|                             # 标签位置,左侧
 | ||
|                             position="left",
 | ||
|                             # 文字字体的粗细,加粗
 | ||
|                             font_weight="bold",
 | ||
|                         ),
 | ||
|                     ))
 | ||
| 
 | ||
|                 chart.render(path)
 | ||
| 
 | ||
| 
 | ||
| """
 |