我用 Python + AI 搭了一套自动化数据分析流水线:从数据清洗到可视化报告,一个脚本搞定

我用 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 条核心经验:

  1. 先清洗再分析。垃圾数据进,垃圾结论出。清洗步骤不能省,缺失值、异常值、重复值都要处理。

  2. AI 洞察需要具体数据。不要只给 AI 一个"数据概览",要把具体的统计数据、趋势、异常值都传给它,它才能给出有价值的建议。

  3. 报告要可交互。Plotly 生成的 HTML 报告可以缩放、筛选、悬停查看详情,比静态图片实用得多。


你有做定期数据分析吗?用什么工具?评论区交流。