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)
|
||
|
||
|
||
"""
|