数据分析实战 #

案例概述 #

本案例将通过一个完整的销售数据分析项目,演示 Pandas 在实际数据分析中的应用。

text
┌─────────────────────────────────────────────────────────────┐
│                    数据分析流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 数据获取                                                │
│     └── 读取数据源                                          │
│                                                             │
│  2. 数据清洗                                                │
│     ├── 处理缺失值                                          │
│     ├── 处理重复值                                          │
│     └── 处理异常值                                          │
│                                                             │
│  3. 数据探索                                                │
│     ├── 描述统计                                            │
│     ├── 分布分析                                            │
│     └── 相关性分析                                          │
│                                                             │
│  4. 数据分析                                                │
│     ├── 分组分析                                            │
│     ├── 时间序列分析                                        │
│     └── 对比分析                                            │
│                                                             │
│  5. 结果输出                                                │
│     ├── 可视化                                              │
│     └── 报告生成                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

准备数据 #

python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

# 生成模拟销售数据
np.random.seed(42)

n_records = 1000

dates = pd.date_range('2023-01-01', '2023-12-31', freq='D')
products = ['Product A', 'Product B', 'Product C', 'Product D', 'Product E']
regions = ['North', 'South', 'East', 'West']
channels = ['Online', 'Store', 'Phone']

sales_data = pd.DataFrame({
    'date': np.random.choice(dates, n_records),
    'product': np.random.choice(products, n_records),
    'region': np.random.choice(regions, n_records),
    'channel': np.random.choice(channels, n_records),
    'quantity': np.random.randint(1, 50, n_records),
    'unit_price': np.random.uniform(10, 100, n_records)
})

# 计算销售额
sales_data['revenue'] = sales_data['quantity'] * sales_data['unit_price']

# 添加一些缺失值和异常值
sales_data.loc[np.random.choice(n_records, 20, replace=False), 'quantity'] = np.nan
sales_data.loc[np.random.choice(n_records, 10, replace=False), 'revenue'] = np.nan

# 添加一些重复值
sales_data = pd.concat([sales_data, sales_data.sample(10)])

print("原始数据:")
print(sales_data.head())
print(f"\n数据形状: {sales_data.shape}")

数据清洗 #

检查数据质量 #

python
# 数据信息
print(sales_data.info())

# 缺失值统计
print("\n缺失值统计:")
print(sales_data.isna().sum())

# 重复值统计
print(f"\n重复值数量: {sales_data.duplicated().sum()}")

# 数据类型
print("\n数据类型:")
print(sales_data.dtypes)

处理缺失值 #

python
# 删除完全重复的行
sales_data = sales_data.drop_duplicates()

# 填充缺失值
sales_data['quantity'] = sales_data['quantity'].fillna(sales_data['quantity'].median())
sales_data['revenue'] = sales_data['revenue'].fillna(sales_data['quantity'] * sales_data['unit_price'])

# 检查缺失值
print("处理后缺失值:")
print(sales_data.isna().sum())

处理异常值 #

python
# 检测异常值
def detect_outliers_iqr(df, column):
    Q1 = df[column].quantile(0.25)
    Q3 = df[column].quantile(0.75)
    IQR = Q3 - Q1
    lower = Q1 - 1.5 * IQR
    upper = Q3 + 1.5 * IQR
    return df[(df[column] < lower) | (df[column] > upper)]

outliers_quantity = detect_outliers_iqr(sales_data, 'quantity')
outliers_revenue = detect_outliers_iqr(sales_data, 'revenue')

print(f"数量异常值: {len(outliers_quantity)}")
print(f"销售额异常值: {len(outliers_revenue)}")

# 处理异常值(用边界值替换)
Q1 = sales_data['quantity'].quantile(0.25)
Q3 = sales_data['quantity'].quantile(0.75)
IQR = Q3 - Q1
sales_data['quantity'] = sales_data['quantity'].clip(Q1 - 1.5 * IQR, Q3 + 1.5 * IQR)

数据探索 #

描述统计 #

python
# 数值列统计
print("数值列统计:")
print(sales_data.describe())

# 分类列统计
print("\n分类列统计:")
for col in ['product', 'region', 'channel']:
    print(f"\n{col}:")
    print(sales_data[col].value_counts())

分布分析 #

python
# 销售额分布
fig, axes = plt.subplots(1, 2, figsize=(12, 4))

sales_data['revenue'].hist(bins=50, ax=axes[0])
axes[0].set_title('Revenue Distribution')
axes[0].set_xlabel('Revenue')
axes[0].set_ylabel('Frequency')

sales_data['quantity'].hist(bins=30, ax=axes[1])
axes[1].set_title('Quantity Distribution')
axes[1].set_xlabel('Quantity')

plt.tight_layout()
plt.show()

数据分析 #

产品分析 #

python
# 按产品分组
product_analysis = sales_data.groupby('product').agg({
    'revenue': ['sum', 'mean', 'count'],
    'quantity': 'sum'
}).round(2)

product_analysis.columns = ['total_revenue', 'avg_revenue', 'transaction_count', 'total_quantity']
product_analysis = product_analysis.sort_values('total_revenue', ascending=False)

print("产品分析:")
print(product_analysis)

# 可视化
product_analysis['total_revenue'].plot(kind='bar', figsize=(10, 5))
plt.title('Revenue by Product')
plt.xlabel('Product')
plt.ylabel('Total Revenue')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

区域分析 #

python
# 按区域分组
region_analysis = sales_data.groupby('region').agg({
    'revenue': 'sum',
    'quantity': 'sum'
}).sort_values('revenue', ascending=False)

print("区域分析:")
print(region_analysis)

# 饼图
region_analysis['revenue'].plot(kind='pie', autopct='%1.1f%%', figsize=(8, 8))
plt.title('Revenue Distribution by Region')
plt.ylabel('')
plt.show()

渠道分析 #

python
# 按渠道分组
channel_analysis = sales_data.groupby('channel').agg({
    'revenue': ['sum', 'mean'],
    'quantity': 'sum'
})

channel_analysis.columns = ['total_revenue', 'avg_revenue', 'total_quantity']
print("渠道分析:")
print(channel_analysis)

时间序列分析 #

python
# 按日期分组
sales_data['date'] = pd.to_datetime(sales_data['date'])
daily_sales = sales_data.groupby('date')['revenue'].sum()

# 月度销售
monthly_sales = daily_sales.resample('M').sum()

# 可视化
fig, axes = plt.subplots(2, 1, figsize=(12, 8))

daily_sales.plot(ax=axes[0])
axes[0].set_title('Daily Sales')
axes[0].set_xlabel('Date')
axes[0].set_ylabel('Revenue')

monthly_sales.plot(kind='bar', ax=axes[1])
axes[1].set_title('Monthly Sales')
axes[1].set_xlabel('Month')
axes[1].set_ylabel('Revenue')
axes[1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

多维度分析 #

python
# 产品-区域交叉分析
pivot_table = pd.pivot_table(
    sales_data, 
    values='revenue', 
    index='product', 
    columns='region', 
    aggfunc='sum',
    fill_value=0
)

print("产品-区域交叉分析:")
print(pivot_table)

# 热力图
import seaborn as sns

plt.figure(figsize=(10, 6))
sns.heatmap(pivot_table, annot=True, fmt='.0f', cmap='YlOrRd')
plt.title('Revenue by Product and Region')
plt.tight_layout()
plt.show()

分析报告 #

python
def generate_report(df):
    print("=" * 60)
    print("销售数据分析报告")
    print("=" * 60)
    
    print("\n1. 数据概览")
    print(f"   - 记录数: {len(df)}")
    print(f"   - 日期范围: {df['date'].min()} 至 {df['date'].max()}")
    print(f"   - 总销售额: ${df['revenue'].sum():,.2f}")
    print(f"   - 平均订单金额: ${df['revenue'].mean():,.2f}")
    
    print("\n2. 产品表现")
    top_product = df.groupby('product')['revenue'].sum().idxmax()
    print(f"   - 最畅销产品: {top_product}")
    
    print("\n3. 区域表现")
    top_region = df.groupby('region')['revenue'].sum().idxmax()
    print(f"   - 最佳区域: {top_region}")
    
    print("\n4. 渠道表现")
    top_channel = df.groupby('channel')['revenue'].sum().idxmax()
    print(f"   - 最佳渠道: {top_channel}")
    
    print("\n5. 时间趋势")
    monthly = df.groupby(df['date'].dt.to_period('M'))['revenue'].sum()
    best_month = monthly.idxmax()
    print(f"   - 最佳月份: {best_month}")
    
    print("\n" + "=" * 60)

generate_report(sales_data)

下一步 #

完成实战案例后,接下来学习 数据管道,了解如何构建可复用的数据处理流程!

最后更新:2026-04-04