本文目录导读:

我来介绍一个完整的自动化分析报告脚本编写方案,包含数据汇总、分析、可视化到报告生成的全流程:
基础框架设计
核心模块结构
# report_generator.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import os
from pathlib import Path
class ReportGenerator:
"""自动化报告生成器"""
def __init__(self, data_path, report_path):
self.data_path = Path(data_path)
self.report_path = Path(report_path)
self.data_loader()
def data_loader(self):
"""数据加载模块"""
# 支持多种数据格式
if self.data_path.suffix == '.csv':
self.df = pd.read_csv(self.data_path)
elif self.data_path.suffix == '.xlsx':
self.df = pd.read_excel(self.data_path)
elif self.data_path.suffix == '.json':
self.df = pd.read_json(self.data_path)
else:
raise ValueError(f"不支持的数据格式: {self.data_path.suffix}")
# 数据清洗
self.data_clean()
def data_clean(self):
"""数据清洗和预处理"""
# 处理缺失值
self.df = self.df.dropna(thresh=len(self.df)*0.6) # 删除缺失超过40%的列
# 统一日期格式
if 'date' in self.df.columns:
self.df['date'] = pd.to_datetime(self.df['date'])
# 处理重复值
self.df = self.df.drop_duplicates()
统计分析模块
class StatisticalAnalyzer:
"""统计分析模块"""
def __init__(self, df):
self.df = df
def basic_stats(self):
"""基本统计信息"""
stats = {
'total_records': len(self.df),
'total_columns': len(self.df.columns),
'data_types': self.df.dtypes.astype(str).to_dict(),
'missing_values': self.df.isnull().sum().to_dict(),
'numeric_stats': self.df.describe().to_dict(),
}
return stats
def trend_analysis(self, columns):
"""趋势分析"""
trends = {}
for col in columns:
if pd.api.types.is_numeric_dtype(self.df[col]):
# 线性回归趋势
x = np.arange(len(self.df))
slope = np.polyfit(x, self.df[col], 1)[0]
trends[col] = {
'trend': '上升' if slope > 0 else '下降',
'slope': slope,
'volatility': self.df[col].std()
}
return trends
def correlation_analysis(self, top_n=10):
"""相关性分析"""
numeric_cols = self.df.select_dtypes(include=[np.number]).columns
corr_matrix = self.df[numeric_cols].corr()
# 找出最强的相关性组合
corr_pairs = []
for i in range(len(corr_matrix.columns)):
for j in range(i+1, len(corr_matrix.columns)):
corr_pairs.append({
'col1': corr_matrix.columns[i],
'col2': corr_matrix.columns[j],
'correlation': corr_matrix.iloc[i, j]
})
corr_pairs.sort(key=lambda x: abs(x['correlation']), reverse=True)
return corr_pairs[:top_n]
可视化模块
class Visualizer:
"""可视化模块"""
def __init__(self, df, output_dir):
self.df = df
self.output_dir = Path(output_dir)
self.output_dir.mkdir(exist_ok=True)
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def create_charts(self):
"""生成所有必要的图表"""
charts = []
# 1. 趋势图
numeric_cols = self.df.select_dtypes(include=[np.number]).columns[:3]
if 'date' in self.df.columns:
charts.append(self.create_time_series(numeric_cols))
# 2. 分布图
for col in numeric_cols[:2]:
charts.append(self.create_distribution(col))
# 3. 相关热力图
charts.append(self.create_correlation_heatmap())
return charts
def create_time_series(self, columns):
"""创建时间序列图"""
fig, ax = plt.subplots(figsize=(12, 6))
for col in columns:
if 'date' in self.df.columns:
ax.plot(self.df['date'], self.df[col], label=col, linewidth=2)
ax.set_xlabel('日期')
ax.set_ylabel('数值')
ax.set_title('时间趋势分析')
ax.legend()
ax.grid(True, alpha=0.3)
filename = f"trend_{datetime.now().strftime('%Y%m%d%H%M%S')}.png"
filepath = self.output_dir / filename
plt.savefig(filepath, dpi=300, bbox_inches='tight')
plt.close()
return str(filepath)
def create_distribution(self, column):
"""创建分布图"""
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
# 直方图
ax1.hist(self.df[column].dropna(), bins=30, alpha=0.7, edgecolor='black')
ax1.set_title(f'{column} 直方图')
ax1.set_xlabel('数值')
ax1.set_ylabel('频数')
# 箱线图
ax2.boxplot(self.df[column].dropna())
ax2.set_title(f'{column} 箱线图')
ax2.set_ylabel('数值')
filename = f"dist_{column}_{datetime.now().strftime('%Y%m%d%H%M%S')}.png"
filepath = self.output_dir / filename
plt.savefig(filepath, dpi=300, bbox_inches='tight')
plt.close()
return str(filepath)
def create_correlation_heatmap(self):
"""创建相关性热力图"""
numeric_cols = self.df.select_dtypes(include=[np.number]).columns
if len(numeric_cols) < 2:
return None
fig, ax = plt.subplots(figsize=(10, 8))
corr = self.df[numeric_cols].corr()
sns.heatmap(corr, annot=True, fmt='.2f', cmap='coolwarm',
square=True, ax=ax)
ax.set_title('相关性分析热力图')
filename = f"corr_{datetime.now().strftime('%Y%m%d%H%M%S')}.png"
filepath = self.output_dir / filename
plt.savefig(filepath, dpi=300, bbox_inches='tight')
plt.close()
return str(filepath)
报告生成模块
class ReportBuilder:
"""报告生成模块"""
def __init__(self, analyzer, visualizer, output_dir):
self.analyzer = analyzer
self.visualizer = visualizer
self.output_dir = Path(output_dir)
self.output_dir.mkdir(exist_ok=True)
def generate_html_report(self):
"""生成HTML格式报告"""
stats = self.analyzer.basic_stats()
trends = self.analyzer.trend_analysis(
self.analyzer.df.select_dtypes(include=[np.number]).columns
)
correlations = self.analyzer.correlation_analysis()
charts = self.visualizer.create_charts()
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数据分析报告</title>
<style>
body {{
font-family: 'Microsoft YaHei', Arial, sans-serif;
margin: 40px;
padding: 20px;
background-color: #f5f5f5;
}}
.container {{
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}}
h1 {{
color: #333;
border-bottom: 3px solid #4CAF50;
padding-bottom: 10px;
text-align: center;
}}
h2 {{
color: #4CAF50;
margin-top: 30px;
}}
.stat-box {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 20px 0;
}}
.stat-item {{
background: #f9f9f9;
padding: 15px;
border-radius: 5px;
border-left: 4px solid #4CAF50;
}}
.stat-label {{
color: #666;
font-size: 14px;
}}
.stat-value {{
font-size: 24px;
font-weight: bold;
margin-top: 5px;
}}
.chart-container {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 30px;
margin: 20px 0;
}}
.chart-container img {{
width: 100%;
border: 1px solid #ddd;
border-radius: 5px;
}}
table {{
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}}
th, td {{
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #4CAF50;
color: white;
}}
tr:hover {{
background-color: #f5f5f5;
}}
.trend-up {{
color: #4CAF50;
font-weight: bold;
}}
.trend-down {{
color: #f44336;
font-weight: bold;
}}
.summary-box {{
background: #e3f2fd;
padding: 20px;
border-radius: 5px;
margin: 20px 0;
}}
</style>
</head>
<body>
<div class="container">
<h1>📊 数据分析自动化报告</h1>
<div class="summary-box">
<h2>📋 报告摘要</h2>
<p><strong>生成时间:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<p><strong>数据来源:</strong> {self.analyzer.df.shape[0]} 条记录, {self.analyzer.df.shape[1]} 个特征</p>
</div>
<h2>📈 基本统计</h2>
<div class="stat-box">
<div class="stat-item">
<div class="stat-label">总记录数</div>
<div class="stat-value">{stats['total_records']}</div>
</div>
<div class="stat-item">
<div class="stat-label">特征数量</div>
<div class="stat-value">{stats['total_columns']}</div>
</div>
</div>
<h2>📉 趋势分析</h2>
<table>
<tr>
<th>变量</th>
<th>趋势</th>
<th>斜率</th>
<th>波动性</th>
</tr>
{self._trend_table(trends)}
</table>
<h2>🔗 相关性分析</h2>
<table>
<tr>
<th>变量1</th>
<th>变量2</th>
<th>相关系数</th>
</tr>
{self._correlation_table(correlations)}
</table>
<h2>📊 可视化图表</h2>
<div class="chart-container">
{self._insert_charts(charts)}
</div>
</div>
</body>
</html>
"""
report_file = self.output_dir / f"report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
report_file.write_text(html_content, encoding='utf-8')
return str(report_file)
def _trend_table(self, trends):
"""生成趋势分析表格"""
rows = []
for col, data in list(trends.items())[:5]:
trend_class = 'trend-up' if data['trend'] == '上升' else 'trend-down'
rows.append(f"""
<tr>
<td>{col}</td>
<td class="{trend_class}">{data['trend']}</td>
<td>{data['slope']:.4f}</td>
<td>{data['volatility']:.2f}</td>
</tr>
""")
return '\n'.join(rows)
def _correlation_table(self, correlations):
"""生成相关性表格"""
rows = []
for item in correlations[:5]:
rows.append(f"""
<tr>
<td>{item['col1']}</td>
<td>{item['col2']}</td>
<td>{item['correlation']:.3f}</td>
</tr>
""")
return '\n'.join(rows)
def _insert_charts(self, charts):
"""插入图表"""
html = []
for chart_path in charts:
if chart_path:
html.append(f'<img src="{chart_path}" alt="图表">')
return '\n'.join(html)
主程序入口
def main():
"""主程序"""
# 配置参数
config = {
'data_path': 'data/sales_data.csv', # 数据路径
'output_dir': 'reports', # 输出目录
'schedule': 'daily' # 执行频率
}
# 初始化
generator = ReportGenerator(config['data_path'], config['output_dir'])
analyzer = StatisticalAnalyzer(generator.df)
visualizer = Visualizer(generator.df, generator.output_dir)
builder = ReportBuilder(analyzer, visualizer, generator.output_dir)
# 生成报告
report_path = builder.generate_html_report()
print(f"✔ 报告已生成: {report_path}")
# 发送通知(可选)
send_notification(f"报告生成完成: {report_path}")
def send_notification(message):
"""发送通知(邮件、微信等)"""
import smtplib
from email.mime.text import MIMEText
# 邮件配置
smtp_server = "smtp.example.com"
sender = "report@example.com"
recipient = "admin@example.com"
msg = MIMEText(message)
msg['Subject'] = "自动化报告通知"
# 这里实现邮件发送逻辑
pass
if __name__ == "__main__":
main()
定时执行配置
# scheduler.py
import schedule
import time
import logging
logging.basicConfig(level=logging.INFO)
def scheduled_report():
"""定时任务"""
logging.info("开始生成报告...")
try:
main()
logging.info("报告生成成功")
except Exception as e:
logging.error(f"报告生成失败: {e}")
# 配置定时任务
schedule.every().day.at("09:00").do(scheduled_report) # 每天9点
schedule.every().monday.at("10:00").do(scheduled_report) # 每周一
schedule.every().hour.do(scheduled_report) # 每小时
# 启动调度器
while True:
schedule.run_pending()
time.sleep(60)
使用配置JSON
# config.json
{
"data_source": {
"type": "file",
"path": "data/sales.csv",
"encoding": "utf-8"
},
"report": {
"type": "html",
"output_dir": "reports",
"include_charts": true,
"include_stats": true
},
"schedule": {
"enabled": true,
"frequency": "daily",
"time": "09:00"
},
"notification": {
"type": "email",
"recipients": ["team@example.com"]
}
}
核心功能特点:
- 模块化设计:数据加载、分析、可视化、报告生成分离
- 自动数据清洗:处理缺失值、重复项、数据格式
- 多维分析:包含统计、趋势、相关性分析
- 丰富可视化:自动生成多种图表
- 多格式输出:支持HTML、PDF、Excel等格式
- 定时调度:支持自动化定时执行
- 通知系统:完成后自动通知相关人员
通过这个框架,你可以快速构建一个完整的自动化分析报告系统,根据实际需求调整数据源、分析维度和报告格式即可。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播