Python实例题:Python实现从excel读取数据并绘制成精美图像
Python实现从excel读取数据并绘制成精美图像。
·
目录
Python实例题
题目
Python实现从excel读取数据并绘制成精美图像
代码实现
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from openpyxl import load_workbook
import os
import argparse
class ExcelChartGenerator:
def __init__(self):
# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题
sns.set_style("whitegrid") # 设置图表风格
def read_excel(self, file_path, sheet_name=0, header=0):
"""读取Excel文件并返回DataFrame"""
try:
df = pd.read_excel(file_path, sheet_name=sheet_name, header=header)
print(f"成功读取Excel文件: {file_path}")
print(f"数据基本信息:")
df.info()
return df
except Exception as e:
print(f"读取Excel文件失败: {e}")
return None
def plot_line_chart(self, df, x_col, y_cols, title="折线图",
xlabel="X轴", ylabel="Y轴", figsize=(10, 6),
save_path=None, show=True):
"""绘制折线图"""
plt.figure(figsize=figsize)
if isinstance(y_cols, str):
y_cols = [y_cols]
for col in y_cols:
plt.plot(df[x_col], df[col], marker='o', linewidth=2, label=col)
plt.title(title, fontsize=15)
plt.xlabel(xlabel, fontsize=12)
plt.ylabel(ylabel, fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
def plot_bar_chart(self, df, x_col, y_col, title="柱状图",
xlabel="X轴", ylabel="Y轴", figsize=(10, 6),
save_path=None, show=True, horizontal=False, color='skyblue'):
"""绘制柱状图"""
plt.figure(figsize=figsize)
if horizontal:
plt.barh(df[x_col], df[y_col], color=color)
else:
plt.bar(df[x_col], df[y_col], color=color)
plt.title(title, fontsize=15)
plt.xlabel(xlabel, fontsize=12)
plt.ylabel(ylabel, fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
def plot_pie_chart(self, df, values_col, labels_col, title="饼图",
figsize=(8, 6), save_path=None, show=True, autopct='%1.1f%%'):
"""绘制饼图"""
plt.figure(figsize=figsize)
plt.pie(df[values_col], labels=df[labels_col], autopct=autopct,
shadow=True, startangle=90, textprops={'fontsize': 10})
plt.axis('equal') # 使饼图为正圆形
plt.title(title, fontsize=15)
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
def plot_scatter_chart(self, df, x_col, y_col, title="散点图",
xlabel="X轴", ylabel="Y轴", figsize=(10, 6),
save_path=None, show=True, color='blue', alpha=0.7):
"""绘制散点图"""
plt.figure(figsize=figsize)
plt.scatter(df[x_col], df[y_col], color=color, alpha=alpha)
plt.title(title, fontsize=15)
plt.xlabel(xlabel, fontsize=12)
plt.ylabel(ylabel, fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
def plot_heatmap(self, df, title="热力图", figsize=(10, 8),
save_path=None, show=True, annot=True, cmap='coolwarm'):
"""绘制热力图"""
plt.figure(figsize=figsize)
# 计算相关系数矩阵
corr = df.corr()
# 绘制热力图
sns.heatmap(corr, annot=annot, cmap=cmap, square=True,
linewidths=.5, cbar_kws={"shrink": .8})
plt.title(title, fontsize=15)
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
def plot_boxplot(self, df, column, group_by=None, title="箱线图",
figsize=(10, 6), save_path=None, show=True):
"""绘制箱线图"""
plt.figure(figsize=figsize)
if group_by:
df.boxplot(column=column, by=group_by)
plt.title(title, fontsize=15)
plt.suptitle('') # 去掉pandas自动添加的标题
else:
plt.boxplot(df[column].dropna())
plt.title(title, fontsize=15)
plt.xticks([1], [column])
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
def plot_histogram(self, df, column, title="直方图",
xlabel="X轴", ylabel="频率", figsize=(10, 6),
save_path=None, show=True, bins=10, color='skyblue'):
"""绘制直方图"""
plt.figure(figsize=figsize)
plt.hist(df[column].dropna(), bins=bins, color=color, alpha=0.7)
plt.title(title, fontsize=15)
plt.xlabel(xlabel, fontsize=12)
plt.ylabel(ylabel, fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"图表已保存至: {save_path}")
if show:
plt.show()
plt.close()
# 使用示例
if __name__ == "__main__":
# 创建命令行参数解析器
parser = argparse.ArgumentParser(description='Excel数据可视化工具')
parser.add_argument('--file', type=str, help='Excel文件路径')
parser.add_argument('--sheet', type=str, default=0, help='工作表名称或索引')
parser.add_argument('--type', type=str, choices=['line', 'bar', 'pie', 'scatter', 'heatmap', 'boxplot', 'histogram'],
help='图表类型')
parser.add_argument('--x', type=str, help='X轴列名')
parser.add_argument('--y', type=str, nargs='+', help='Y轴列名(可多个)')
parser.add_argument('--title', type=str, default='数据可视化', help='图表标题')
parser.add_argument('--output', type=str, help='图表保存路径')
args = parser.parse_args()
# 如果没有提供命令行参数,使用示例数据
if not args.file:
# 创建示例数据
data = {
'日期': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'],
'销售额': [12000, 19000, 15000, 21000, 25000],
'利润': [3500, 5200, 4100, 6500, 7200],
'成本': [8500, 13800, 10900, 14500, 17800]
}
df = pd.DataFrame(data)
# 创建图表生成器实例
generator = ExcelChartGenerator()
# 绘制折线图
generator.plot_line_chart(
df,
x_col='日期',
y_cols=['销售额', '利润', '成本'],
title='月度销售数据趋势',
xlabel='日期',
ylabel='金额(元)'
)
# 绘制柱状图
generator.plot_bar_chart(
df,
x_col='日期',
y_col='销售额',
title='月度销售额',
xlabel='日期',
ylabel='销售额(元)',
color='skyblue'
)
# 绘制饼图
profit_data = {
'部门': ['销售部', '研发部', '市场部', '财务部', '人力资源部'],
'利润贡献': [45, 25, 15, 10, 5]
}
profit_df = pd.DataFrame(profit_data)
generator.plot_pie_chart(
profit_df,
values_col='利润贡献',
labels_col='部门',
title='各部门利润贡献占比'
)
# 绘制散点图
scatter_data = {
'广告投入': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
'销售额': [150, 200, 250, 300, 350, 400, 450, 500, 550, 600]
}
scatter_df = pd.DataFrame(scatter_data)
generator.plot_scatter_chart(
scatter_df,
x_col='广告投入',
y_col='销售额',
title='广告投入与销售额关系',
xlabel='广告投入(万元)',
ylabel='销售额(万元)'
)
# 绘制热力图
heatmap_data = {
'温度': [20, 22, 25, 28, 30, 32, 31, 29, 27, 25],
'湿度': [60, 65, 70, 75, 80, 85, 82, 78, 72, 68],
'销量': [120, 135, 150, 165, 180, 195, 190, 175, 160, 145]
}
heatmap_df = pd.DataFrame(heatmap_data)
generator.plot_heatmap(
heatmap_df,
title='温度、湿度与销量的相关性热力图'
)
# 绘制箱线图
boxplot_data = {
'产品': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'],
'评分': [85, 90, 88, 92, 87, 75, 78, 82, 80, 79]
}
boxplot_df = pd.DataFrame(boxplot_data)
generator.plot_boxplot(
boxplot_df,
column='评分',
group_by='产品',
title='不同产品评分分布'
)
# 绘制直方图
hist_data = {
'年龄': [22, 25, 28, 30, 32, 35, 38, 40, 42, 45, 48, 50, 52, 55, 58, 60]
}
hist_df = pd.DataFrame(hist_data)
generator.plot_histogram(
hist_df,
column='年龄',
title='年龄分布',
xlabel='年龄',
ylabel='人数',
bins=5
)
print("已使用示例数据生成所有类型的图表")
else:
# 使用命令行参数指定的Excel文件
if not args.type:
print("请指定图表类型(--type)")
sys.exit(1)
if args.type in ['line', 'bar', 'scatter'] and not args.x:
print(f"图表类型 {args.type} 需要指定X轴列名(--x)")
sys.exit(1)
if args.type in ['line', 'bar', 'scatter'] and not args.y:
print(f"图表类型 {args.type} 需要指定Y轴列名(--y)")
sys.exit(1)
if args.type == 'pie' and (len(args.y) != 1 or not args.x):
print("饼图需要指定一个Y轴列名(--y)和一个标签列名(--x)")
sys.exit(1)
# 创建图表生成器实例
generator = ExcelChartGenerator()
# 读取Excel文件
df = generator.read_excel(args.file, sheet_name=args.sheet)
if df is None:
print("无法读取Excel文件,程序退出")
sys.exit(1)
# 根据指定的图表类型生成图表
if args.type == 'line':
generator.plot_line_chart(
df,
x_col=args.x,
y_cols=args.y,
title=args.title,
save_path=args.output
)
elif args.type == 'bar':
generator.plot_bar_chart(
df,
x_col=args.x,
y_col=args.y[0],
title=args.title,
save_path=args.output
)
elif args.type == 'pie':
generator.plot_pie_chart(
df,
values_col=args.y[0],
labels_col=args.x,
title=args.title,
save_path=args.output
)
elif args.type == 'scatter':
generator.plot_scatter_chart(
df,
x_col=args.x,
y_col=args.y[0],
title=args.title,
save_path=args.output
)
elif args.type == 'heatmap':
generator.plot_heatmap(
df,
title=args.title,
save_path=args.output
)
elif args.type == 'boxplot':
generator.plot_boxplot(
df,
column=args.y[0],
group_by=args.x if args.x else None,
title=args.title,
save_path=args.output
)
elif args.type == 'histogram':
generator.plot_histogram(
df,
column=args.y[0],
title=args.title,
save_path=args.output
)
实现原理
这个 Excel 数据可视化工具基于以下核心技术实现:
-
数据读取:
- 使用 pandas 读取 Excel 文件
- 支持指定工作表和表头行
-
图表绘制:
- 基于 matplotlib 和 seaborn 库
- 提供多种图表类型(折线图、柱状图、饼图等)
- 自定义图表样式和布局
-
模块化设计:
- 每个图表类型对应一个独立方法
- 统一的参数接口和样式配置
- 支持图表保存和显示
关键代码解析
数据读取与预处理
def read_excel(self, file_path, sheet_name=0, header=0):
try:
df = pd.read_excel(file_path, sheet_name=sheet_name, header=header)
print(f"成功读取Excel文件: {file_path}")
df.info() # 打印数据基本信息
return df
except Exception as e:
print(f"读取Excel文件失败: {e}")
return None
折线图绘制
def plot_line_chart(self, df, x_col, y_cols, title="折线图",
xlabel="X轴", ylabel="Y轴", figsize=(10, 6),
save_path=None, show=True):
plt.figure(figsize=figsize)
for col in y_cols:
plt.plot(df[x_col], df[col], marker='o', linewidth=2, label=col)
plt.title(title, fontsize=15)
plt.xlabel(xlabel, fontsize=12)
plt.ylabel(ylabel, fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
if show:
plt.show()
plt.close()
热力图绘制
def plot_heatmap(self, df, title="热力图", figsize=(10, 8),
save_path=None, show=True, annot=True, cmap='coolwarm'):
plt.figure(figsize=figsize)
# 计算相关系数矩阵
corr = df.corr()
# 使用seaborn绘制热力图
sns.heatmap(corr, annot=annot, cmap=cmap, square=True,
linewidths=.5, cbar_kws={"shrink": .8})
plt.title(title, fontsize=15)
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
if show:
plt.show()
plt.close()
使用说明
-
安装依赖:
pip install pandas matplotlib seaborn openpyxl argparse
-
基本用法:
# 创建实例
generator = ExcelChartGenerator()
# 读取Excel数据
df = generator.read_excel("data.xlsx")
# 绘制折线图
generator.plot_line_chart(
df,
x_col="日期",
y_cols=["销售额", "利润"],
title="销售趋势分析"
)
-
命令行使用:
# 使用示例数据生成所有类型的图表
python excel_chart_generator.py
# 从Excel文件读取数据并生成柱状图
python excel_chart_generator.py --file sales_data.xlsx --sheet Sheet1 --type bar --x 产品 --y 销量 --title "产品销量对比" --output sales_bar.png
扩展建议
-
增强功能:
- 添加 3D 图表支持
- 实现交互式图表(使用 plotly)
- 支持图表组合和子图
-
样式优化:
- 添加更多预设样式主题
- 支持自定义颜色和字体
- 优化中文显示效果
-
高级功能:
- 添加数据预处理和清洗功能
- 实现统计分析和趋势预测
- 支持导出为 PDF 或其他格式
-
用户界面:
- 开发 Web 界面(Flask/Django)
- 制作桌面应用(PyQt/Tkinter)
- 添加图形化参数配置界面
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐




所有评论(0)