Python 自动化实战:数据分析自动化——Pandas 实战

PythonPandas数据分析自动化独立开发

独立开发者为什么要学数据分析?

说个真事。

去年我做了一个 Chrome 插件,付费用户大概 2000 人。有一天我想分析"哪些功能的用户用得最多,哪些功能从来没人碰"——于是打开 Google Analytics,点来点去,导出 CSV,再拖进 Excel,做透视表,画图……前后搞了将近两小时。得出的结论是:三个功能占了 90% 的使用量,另外五个功能根本没人用。

那个结论确实有价值——它让我砍掉了没人用的功能,把精力集中到核心上。可问题是:我花了两个小时做了一件可以用 10 行 Python 代码自动完成的事

之后我写了个脚本,每周自动跑一次,产出同样的分析报告。从那以后,我再也没手动拖过 Excel。

这就是 Pandas 的力量。它不是你想象中的"数据科学家专用工具"——对独立开发者来说,它是决策加速器。用户行为、营收趋势、竞品数据、SEO 关键词效果……这些事每次手动分析都是在浪费时间,而它们恰好是 Pandas 最擅长干的。

数据分析自动化流程

数据分析自动化流程

整个流程就六步。这篇文章我会用两个实战案例跑通这个流程。一个是你自己的业务数据(CSV 文件),一个是你在上篇文章里通过 API 拉回来的外部数据。看完你会有一个通用的分析模板,以后替换数据源即可复用。

环境准备

pip install pandas matplotlib numpy openpyxl

openpyxl 用于读写 Excel,matplotlib 用于画图。装完就可以开工。

实战一:用户行为数据分析

假设你是独立开发者,有一个小产品。你记录了用户的行为日志,CSV 格式,字段包括:user_id(用户ID)、event(行为类型)、date(日期)、duration_sec(耗时秒数)。

真实数据长这样:

user_ideventdateduration_sec
u001page_view2026-06-180
u001feature_click2026-06-1845
u001export2026-06-18120
u002page_view2026-06-190
u002page_view2026-06-190

第一步:加载数据

import pandas as pd

df = pd.read_csv("user_events.csv")
print(df.head())
print(f"总行数:{len(df)},用户数:{df['user_id'].nunique()}")

read_csv() 是最常用的入口。Pandas 支持 CSV、Excel、JSON、SQL、Parquet 等二十多种格式,几乎覆盖了你遇到的所有数据源。

第二步:清洗数据

# 检查缺失值
print(df.isnull().sum())

# 检查重复
duplicates = df.duplicated().sum()
print(f"重复行:{duplicates}")

# 转换日期类型
df['date'] = pd.to_datetime(df['date'])

# 过滤异常值:duration 不应该超过一天的秒数
df = df[df['duration_sec'] <= 86400]

新手的常见错误是跳过清洗直接分析——然后发现聚合结果是 NaN,或者统计数量莫名其妙多了一倍(因为重复行没去)。这三行检查应该在每次分析前跑一遍。

第三步 & 第四步:聚合分析

真正干活的部分来了:

# 每个事件的总触发次数
event_counts = df.groupby('event').size().sort_values(ascending=False)
print(event_counts)

# 每日活跃用户数(DAU)
dau = df.groupby('date')['user_id'].nunique()
print(dau.head(10))

# 每个事件的平均时长
avg_duration = df[df['duration_sec'] > 0].groupby('event')['duration_sec'].mean()
print(avg_duration)

# 用户留存:至少访问过2天的用户占比
user_active_days = df.groupby('user_id')['date'].nunique()
retention = (user_active_days >= 2).mean() * 100
print(f"次日留存:{retention:.1f}%")

groupby 是 Pandas 的灵魂。它本质上就是 Excel 的透视表,但不需要鼠标点点点——一行代码出来,直接拿去用。

第五步:可视化

import matplotlib.pyplot as plt

# 支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei', 'Noto Sans CJK SC', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 左图:事件频次柱状图
event_counts.plot(kind='bar', ax=axes[0], color='#4A90D9')
axes[0].set_title('功能使用频次')
axes[0].set_ylabel('触发次数')

# 右图:DAU 趋势线
dau.plot(ax=axes[1], marker='o', color='#E85D3F')
axes[1].set_title('每日活跃用户')
axes[1].set_ylabel('用户数')

plt.tight_layout()
plt.savefig('user_analysis.png', dpi=150)
plt.show()

这里有个坑我要特别说:matplotlib 默认不支持中文,图里的中文标签会变成方框。上面 plt.rcParams 那两行是必加的,缺了它你折腾半小时都找不到原因。

第六步:导出报告

# 导出 Excel,一个事件一个 sheet
with pd.ExcelWriter('user_report.xlsx') as writer:
    event_counts.to_frame('count').to_excel(writer, sheet_name='事件统计')
    dau.to_frame('dau').to_excel(writer, sheet_name='每日活跃')
    avg_duration.to_frame('avg_seconds').to_excel(writer, sheet_name='平均耗时')

print("报告已生成:user_report.xlsx")

整个过程不超过 30 行代码。下次要分析,换一个 CSV 文件名就跑。

实战二:API 数据分析

上篇文章我们教了你怎么用 API 拉数据。现在把拉回来的数据和 Pandas 接上。

假设你调了一个加密货币价格 API,拉回来 30 天的历史数据:

import requests
import pandas as pd
from datetime import datetime, timedelta

# 拉取最近 30 天的比特币价格(以 CoinGecko 免费 API 为例)
url = "https://api.coingecko.com/api/v3/coins/bitcoin/market_chart"
params = {
    "vs_currency": "usd",
    "days": "30"
}
resp = requests.get(url, params=params)
data = resp.json()

# 数据在 data['prices'] 里,格式是 [[timestamp, price], ...]
df = pd.DataFrame(data['prices'], columns=['timestamp', 'price'])
df['date'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('date', inplace=True)

# 接下来直接上 Pandas 分析
daily = df['price'].resample('D').agg(['first', 'last', 'max', 'min'])
daily['change_pct'] = ((daily['last'] - daily['first']) / daily['first'] * 100).round(2)

print(daily.tail(7))

复盘一下:API 拉回来 JSON → Pandas 转成 DataFrame → resample 按天聚合 → 算出涨跌幅。过去你可能需要把数据贴到 Excel 里手动算公式,现在这 5 行代码搞定。

再加一段波动率分析:

# 计算 7 日滚动波动率
daily['return'] = daily['last'].pct_change()
daily['volatility_7d'] = daily['return'].rolling(7).std() * (252 ** 0.5) * 100

# 标记涨跌超过 5% 的日期
big_moves = daily[daily['change_pct'].abs() > 5]
print(f"近30天有 {len(big_moves)} 天涨跌幅超过5%:")
print(big_moves[['change_pct']])

pct_change()rolling() 是 Pandas 里我最常用的两个金融分析函数。pct_change() 算逐日收益率,rolling(7).std() 算 7 天滑动标准差——再乘以 252 的平方根就换算成年化波动率(金融领域的标准做法)。

建一个你自己的分析模板

上面两个案例跑完,你会发现不管分析什么数据,代码结构是一样的。我建议你把通用部分抽成一个模板类,以后每次分析只需要改数据源和聚合逻辑:

class DataAnalyzer:
    """通用数据分析模板"""
    
    def __init__(self, source):
        self.df = None
        self.source = source
    
    def load(self, **kwargs):
        """支持多种数据源"""
        if self.source.endswith('.csv'):
            self.df = pd.read_csv(self.source, **kwargs)
        elif self.source.endswith('.xlsx'):
            self.df = pd.read_excel(self.source, **kwargs)
        elif self.source.startswith('http'):
            resp = requests.get(self.source)
            self.df = pd.DataFrame(resp.json())
        elif self.source.startswith('sqlite://'):
            import sqlite3
            conn = sqlite3.connect(self.source.replace('sqlite://', ''))
            self.df = pd.read_sql(kwargs.get('query'), conn)
        print(f"✅ 加载完成:{len(self.df)} 行")
        return self
    
    def clean(self, date_columns=None, drop_duplicates=True):
        if drop_duplicates:
            before = len(self.df)
            self.df.drop_duplicates(inplace=True)
            print(f"去重:{before}{len(self.df)}")
        if date_columns:
            for col in date_columns:
                self.df[col] = pd.to_datetime(self.df[col])
        # 自动填补常见的空值
        for col in self.df.select_dtypes(include='number').columns:
            self.df[col].fillna(0, inplace=True)
        return self
    
    def summarize(self):
        """快速概览"""
        return {
            '行数': len(self.df),
            '列数': len(self.df.columns),
            '缺失值': self.df.isnull().sum().sum(),
            '数值列': list(self.df.select_dtypes(include='number').columns),
            '分类列': list(self.df.select_dtypes(include='object').columns),
        }


# 使用示例
analyzer = DataAnalyzer("user_events.csv")
analyzer.load().clean(date_columns=['date'])
print(analyzer.summarize())

这个模板类是一个起点,不是终点。随着你分析的项目越来越多,你会不断往里加方法——比如自动生成月度对比报告、自动发邮件告警异常值。它就是你自己的"数据分析助手"。

实际受益:我靠这套流程省了多少时间?

说几个我自己用 Pandas 自动化的真实场景:

  1. SEO 关键词监控:每周自动跑一次,对比本周和前一周的排名变化,找出上升和下降的关键词,发到 Telegram。以前每次手动导 Search Console 数据、做对比、写结论,要 40 分钟。现在 0 分钟。

  2. 用户留存分析:从数据库拉用户注册和活跃日志,自动算出 7/14/30 日留存,生成趋势图。以前每两周做一次要半小时,现在每周自动出图。

  3. 竞品价格监控:爬回来的竞品价格数据,Pandas 自动算均值、中位数、最低价,标出异常波动。这件事要是手动做根本不可能——数据量太大。

核心逻辑就一句话:数据只要进了 DataFrame,分析就是几行 groupby 的事。把这几行写成脚本,设成 cron 定时跑,你就再也不用碰 Excel 了。

从这里开始

这篇文章和前面三篇组成了完整的 Python 自动化链路:

  • 文件 & 系统操作(第 01 篇):自动整理、批量处理
  • 数据获取(第 02 篇 Web Scraping + 第 03 篇 API):拿到数据
  • 数据分析(本篇 Pandas):把数据变成洞察
  • 定时调度(下一篇):让一切定期自动运行

建议今天就用上面 DataAnalyzer 模板跑一次你自己的数据。哪怕是导出一份 CSV 的网站访问量,用 groupby 按天聚合然后画一条趋势线——从"手动分析"到"自动化分析"的跨越,就几步代码的事。


系列导航01 日常任务自动化 | 02 Web Scraping 实战 | 03 API 自动化 | 04 数据分析自动化 | 05 定时任务 & 监控(即将更新)

Python 自动化实战系列,下一篇:定时任务 & 监控脚本——把上面所有脚本串起来,让它们定期自动跑。