我用 Python + AI 搭了一套自动化数据分析流水线:从数据清洗到可视化报告,一个脚本搞定
适合需要定期处理数据、生成分析报告的运营、分析师和开发者。
本文用 Python + Pandas + AI 搭了一套完整的数据分析流水线,从数据清洗到统计分析到可视化报告,一个脚本自动完成。
背景:数据分析的重复劳动
每周都要做数据分析:从数据库导出 CSV → 清洗脏数据 → 计算指标 → 做图表 → 写报告。每次花 2-3 小时,流程一模一样。
用 Python 把这个流程自动化,一个脚本 5 分钟搞定。
流水线架构
数据源(CSV/数据库/API)→ 数据清洗 → 统计分析 → AI 洞察 → 可视化报告
模块 1:数据加载与清洗
python
import pandas as pd
import numpy as np
from datetime import datetime
class DataCleaner:
"""数据清洗器"""
def __init__(self, df):
self.df = df.copy()
self.clean_log = []
def clean_all(self):
"""执行全部清洗步骤"""
self.remove_duplicates()
self.handle_missing()
self.fix_dtypes()
self.remove_outliers()
return self.df
def remove_duplicates(self):
"""去重"""
before = len(self.df)
self.df = self.df.drop_duplicates()
after = len(self.df)
if before != after:
self.clean_log.append(f"去重: {before} → {after} 行 (去除 {before - after} 重复)")
return self
def handle_missing(self):
"""处理缺失值"""
missing = self.df.isnull().sum()
missing_cols = missing[missing > 0]
for col in missing_cols.index:
if self.df[col].dtype in ['int64', 'float64']:
self.df[col] = self.df[col].fillna(self.df[col].median())
self.clean_log.append(f"填充缺失: {col} (中位数填充, {missing_cols[col]} 个)")
else:
self.df[col] = self.df[col].fillna("未知")
self.clean_log.append(f"填充缺失: {col} (填充'未知', {missing_cols[col]} 个)")
return self
def fix_dtypes(self):
"""修复数据类型"""
for col in self.df.columns:
# 尝试转换日期列
if self.df[col].dtype == 'object':
try:
self.df[col] = pd.to_datetime(self.df[col])
self.clean_log.append(f"类型修复: {col} → datetime")
except:
pass
return self
def remove_outliers(self, columns=None, method="iqr"):
"""去除异常值"""
if columns is None:
columns = self.df.select_dtypes(include=[np.number]).columns
for col in columns:
Q1 = self.df[col].quantile(0.25)
Q3 = self.df[col].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
before = len(self.df)
self.df = self.df[(self.df[col] >= lower) & (self.df[col] <= upper)]
after = len(self.df)
if before != after:
self.clean_log.append(f"异常值: {col} 去除 {before - after} 行 (范围: {lower:.2f} ~ {upper:.2f})")
return self
模块 2:统计分析
python
class DataAnalyzer:
"""统计分析器"""
def __init__(self, df):
self.df = df
self.insights = []
def basic_stats(self):
"""基础统计"""
numeric_cols = self.df.select_dtypes(include=[np.number]).columns
stats = self.df[numeric_cols].describe().T
stats["missing"] = self.df[numeric_cols].isnull().sum()
return stats
def trend_analysis(self, date_col, value_col, freq="M"):
"""趋势分析"""
if date_col not in self.df.columns:
return None
trend = self.df.set_index(date_col).resample(freq)[value_col].agg(["mean", "sum", "count"])
trend.columns = ["均值", "总量", "数量"]
# 计算环比变化
trend["环比变化"] = trend["总量"].pct_change() * 100
# 自动发现趋势
if len(trend) >= 3:
recent = trend["环比变化"].tail(3).mean()
if recent > 10:
self.insights.append(f"📈 {value_col} 近 3 期平均增长 {recent:.1f}%,呈上升趋势")
elif recent < -10:
self.insights.append(f"📉 {value_col} 近 3 期平均下降 {abs(recent):.1f}%,呈下降趋势")
return trend
def correlation_analysis(self):
"""相关性分析"""
numeric_df = self.df.select_dtypes(include=[np.number])
corr = numeric_df.corr()
# 自动发现强相关
for i in range(len(corr.columns)):
for j in range(i + 1, len(corr.columns)):
if abs(corr.iloc[i, j]) > 0.7:
self.insights.append(
f"🔗 {corr.columns[i]} 和 {corr.columns[j]} 强相关 (r={corr.iloc[i, j]:.2f})"
)
return corr
def top_n_analysis(self, group_col, value_col, n=10):
"""Top N 分析"""
top = self.df.groupby(group_col)[value_col].sum().sort_values(ascending=False).head(n)
return top
模块 3:AI 洞察生成
python
from openai import OpenAI
client = OpenAI()
def generate_ai_insights(df, stats, insights):
"""用 AI 生成数据洞察"""
# 准备数据摘要
summary = f"""
数据概况:
- 行数: {len(df)}
- 列数: {len(df.columns)}
- 数值列: {', '.join(df.select_dtypes(include=[np.number]).columns)}
- 时间范围: {df.select_dtypes(include=['datetime']).min().iloc[0] if len(df.select_dtypes(include=['datetime']).columns) > 0 else 'N/A'}
基础统计:
{stats.to_string()}
自动发现的洞察:
{chr(10).join(insights) if insights else '无特殊发现'}
"""
prompt = f"""你是一个数据分析师。根据以下数据摘要,给出 3-5 条可执行的业务建议。
{summary}
要求:
- 每条建议要有具体的数据支撑
- 指出潜在问题或机会
- 给出可执行的下一步行动
- 用简洁的中文,不要废话"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
模块 4:可视化报告
python
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
class ReportGenerator:
"""可视化报告生成器"""
def __init__(self, df):
self.df = df
def create_dashboard(self, output_path="report.html"):
"""生成交互式报告"""
fig = make_subplots(
rows=2, cols=2,
subplot_titles=("数据分布", "趋势图", "Top 10", "相关性热力图"),
specs=[[{"type": "histogram"}, {"type": "scatter"}],
[{"type": "bar"}, {"type": "heatmap"}]]
)
numeric_cols = self.df.select_dtypes(include=[np.number]).columns
# 图表 1: 分布直方图
if len(numeric_cols) > 0:
fig.add_trace(
go.Histogram(x=self.df[numeric_cols[0]], name=numeric_cols[0]),
row=1, col=1
)
# 图表 2: 趋势图
date_cols = self.df.select_dtypes(include=["datetime"]).columns
if len(date_cols) > 0 and len(numeric_cols) > 0:
fig.add_trace(
go.Scatter(x=self.df[date_cols[0]], y=self.df[numeric_cols[0]], mode="lines", name="趋势"),
row=1, col=2
)
# 图表 3: Top 10
if len(numeric_cols) > 1:
cat_cols = self.df.select_dtypes(include=["object"]).columns
if len(cat_cols) > 0:
top10 = self.df.groupby(cat_cols[0])[numeric_cols[0]].sum().sort_values(ascending=False).head(10)
fig.add_trace(
go.Bar(x=top10.index, y=top10.values, name="Top 10"),
row=2, col=1
)
# 图表 4: 相关性热力图
corr = self.df[numeric_cols].corr()
fig.add_trace(
go.Heatmap(z=corr.values, x=corr.columns, y=corr.index, colorscale="RdBu"),
row=2, col=2
)
fig.update_layout(height=800, showlegend=False, title="数据分析报告")
fig.write_html(output_path)
print(f"报告已生成: {output_path}")
return output_path
模块 5:完整流水线
python
def run_pipeline(data_source, output_dir="reports"):
"""完整数据分析流水线"""
import os
os.makedirs(output_dir, exist_ok=True)
print("📊 数据分析流水线启动\n")
# 1. 加载数据
print("Step 1: 加载数据...")
if isinstance(data_source, str):
df = pd.read_csv(data_source)
else:
df = data_source
print(f" 数据: {len(df)} 行 × {len(df.columns)} 列")
# 2. 数据清洗
print("\nStep 2: 数据清洗...")
cleaner = DataCleaner(df)
df = cleaner.clean_all()
for log in cleaner.clean_log:
print(f" {log}")
# 3. 统计分析
print("\nStep 3: 统计分析...")
analyzer = DataAnalyzer(df)
stats = analyzer.basic_stats()
corr = analyzer.correlation_analysis()
for insight in analyzer.insights:
print(f" {insight}")
# 4. AI 洞察
print("\nStep 4: AI 洞察...")
ai_insights = generate_ai_insights(df, stats, analyzer.insights)
print(f" AI 生成了 {len(ai_insights)} 条建议")
# 5. 可视化报告
print("\nStep 5: 生成报告...")
report = ReportGenerator(df)
report_path = report.create_dashboard(f"{output_dir}/report_{datetime.now().strftime('%Y%m%d')}.html")
# 6. 保存 AI 洞察
with open(f"{output_dir}/insights_{datetime.now().strftime('%Y%m%d')}.md", "w", encoding="utf-8") as f:
f.write(f"# 数据分析报告 {datetime.now().strftime('%Y-%m-%d')}\n\n")
f.write("## AI 洞察\n\n")
f.write(ai_insights)
print(f"\n✅ 流水线完成!报告: {report_path}")
return report_path
使用:
python
# 从 CSV 文件
run_pipeline("sales_data.csv")
# 从数据库
import sqlite3
conn = sqlite3.connect("business.db")
df = pd.read_sql("SELECT * FROM orders", conn)
run_pipeline(df)
踩坑记录
坑 1:日期格式不统一
症状:同一列有 "2024-01-01"、"2024/1/1"、"01-01-2024" 三种格式。
原因:数据来源不同,格式不统一。
解决 :用 pd.to_datetime(errors="coerce") 自动识别,不能识别的变成 NaT,后面再处理。
坑 2:数值列混入非数值
症状:金额列有 "¥100"、"100元"、"暂无" 等非纯数字。
解决:清洗时用正则提取数字:
python
df["amount"] = df["amount"].astype(str).str.extract(r'(\d+\.?\d*)')[0].astype(float)
坑 3:AI 洞察太泛
症状:AI 说"建议优化产品",没有具体方向。
原因:给 AI 的数据摘要太简略。
解决:把具体的统计数据(Top 5、趋势变化、异常值)都传给 AI,它才能给出具体建议。
坑 4:Plotly 图表在 CSDN 上不显示
症状:生成的 HTML 图表在 CSDN 文章里显示空白。
原因:CSDN 不支持 JavaScript 渲染。
解决:同时生成 PNG 静态图片版本:
python
fig.write_image("report.png", width=1200, height=800)
坑 5:大数据量内存爆
症状:1000 万行数据读取时内存不足。
解决:用 chunksize 分块读取:
python
chunks = pd.read_csv("big_data.csv", chunksize=100000)
df = pd.concat([chunk for chunk in chunks])
总结
3 条核心经验:
-
先清洗再分析。垃圾数据进,垃圾结论出。清洗步骤不能省,缺失值、异常值、重复值都要处理。
-
AI 洞察需要具体数据。不要只给 AI 一个"数据概览",要把具体的统计数据、趋势、异常值都传给它,它才能给出有价值的建议。
-
报告要可交互。Plotly 生成的 HTML 报告可以缩放、筛选、悬停查看详情,比静态图片实用得多。
你有做定期数据分析吗?用什么工具?评论区交流。