Python 数据分析入门指南 - 从零基础到实战项目
本文是一份完整的数据分析入门教程,适合零基础学习者。通过一个真实的电商数据分析项目,带你掌握 Python 数据分析的核心技能。
目录
环境搭建
安装 Python
首先确保你安装了 Python 3.8 或更高版本:
# 检查 Python 版本
python --version
# Windows 用户可以从 python.org 下载
# macOS 用户可以使用 Homebrew
brew install python@3.11
# Linux 用户可以使用包管理器
sudo apt-get install python3 python3-pip
创建虚拟环境
# 创建虚拟环境
python -m venv data-analysis-env
# 激活虚拟环境
# Windows
data-analysis-env\Scripts\activate
# macOS/Linux
source data-analysis-env/bin/activate
安装必要的库
pip install pandas numpy matplotlib seaborn jupyter scikit-learn
创建 requirements.txt 文件:
pandas==2.1.0
numpy==1.26.0
matplotlib==3.8.0
seaborn==0.13.0
jupyter==1.0.0
scikit-learn==1.3.0
验证安装
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
print(f"Pandas 版本:{pd.__version__}")
print(f"NumPy 版本:{np.__version__}")
print(f"Matplotlib 版本:{plt.matplotlib.__version__}")
print(f"Seaborn 版本:{sns.__version__}")
输出应该类似:
Pandas 版本:2.1.0
NumPy 版本:1.26.0
Matplotlib 版本:3.8.0
Seaborn 版本:0.13.0
数据加载与探索
创建示例数据集
首先,我们创建一个模拟的电商销售数据集:
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# 设置随机种子以保证结果可复现
np.random.seed(42)
# 生成日期范围
dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='D')
# 生成产品类别
categories = ['电子产品', '服装', '图书', '家居', '食品']
products = {
'电子产品': ['手机', '电脑', '平板', '耳机', '充电器'],
'服装': ['T 恤', '牛仔裤', '外套', '运动鞋', '帽子'],
'图书': ['小说', '教材', '漫画', '杂志', '工具书'],
'家居': ['床单', '台灯', '收纳盒', '抱枕', '地毯'],
'食品': ['零食', '茶叶', '坚果', '饼干', '咖啡']
}
# 生成订单数据
orders = []
for date in dates:
# 每天的订单数量在 10-50 之间随机
num_orders = np.random.randint(10, 51)
for _ in range(num_orders):
category = np.random.choice(categories)
product = np.random.choice(products[category])
quantity = np.random.randint(1, 6)
price = np.random.uniform(10, 5000)
discount = np.random.choice([0, 0.1, 0.2, 0.3], p=[0.5, 0.2, 0.2, 0.1])
customer_id = f"C{np.random.randint(1000, 9999)}"
region = np.random.choice(['华东', '华南', '华北', '西南', '西北'])
orders.append({
'order_id': f"ORD{len(orders)+1:06d}",
'order_date': date,
'customer_id': customer_id,
'category': category,
'product': product,
'quantity': quantity,
'unit_price': round(price, 2),
'discount': discount,
'region': region,
'payment_method': np.random.choice(['支付宝', '微信', '信用卡', '货到付款']),
'rating': np.random.choice([1, 2, 3, 4, 5], p=[0.05, 0.1, 0.2, 0.4, 0.25])
})
# 创建 DataFrame
df = pd.DataFrame(orders)
# 计算订单金额
df['total_amount'] = df['unit_price'] * df['quantity'] * (1 - df['discount'])
# 保存为 CSV
df.to_csv('ecommerce_sales.csv', index=False, encoding='utf-8-sig')
print(f"数据集已创建,共 {len(df)} 条记录")
加载数据
import pandas as pd
# 读取 CSV 文件
df = pd.read_csv('ecommerce_sales.csv', parse_dates=['order_date'])
# 显示前 5 行
print("=== 数据预览 ===")
df.head()
输出示例:
| order_id | order_date | customer_id | category | product | quantity | unit_price | discount | region | payment_method | rating | total_amount |
|---|---|---|---|---|---|---|---|---|---|---|---|
| ORD000001 | 2024-01-01 | C5672 | 电子产品 | 手机 | 2 | 3299.00 | 0.1 | 华东 | 支付宝 | 5 | 5938.20 |
| ORD000002 | 2024-01-01 | C1234 | 服装 | T 恤 | 3 | 89.99 | 0 | 华南 | 微信 | 4 | 269.97 |
| ORD000003 | 2024-01-01 | C8765 | 图书 | 小说 | 1 | 45.00 | 0.2 | 华北 | 支付宝 | 5 | 36.00 |
| ORD000004 | 2024-01-01 | C3456 | 家居 | 台灯 | 2 | 159.00 | 0 | 西南 | 信用卡 | 3 | 318.00 |
| ORD000005 | 2024-01-01 | C7890 | 食品 | 咖啡 | 4 | 68.50 | 0.1 | 西北 | 微信 | 4 | 246.60 |
数据基本信息
print("=== 数据基本信息 ===")
print(f"\n数据形状:{df.shape}")
print(f"\n数据类型:\n{df.dtypes}")
print(f"\n缺失值统计:\n{df.isnull().sum()}")
print(f"\n基本统计信息:\n{df.describe()}")
输出:
=== 数据基本信息 ===
数据形状:(10957, 12)
数据类型:
order_id object
order_date datetime64[ns]
customer_id object
category object
product object
quantity int32
unit_price float64
discount float64
region object
payment_method object
rating int32
total_amount float64
缺失值统计:
order_id 0
order_date 0
customer_id 0
category 0
product 0
quantity 0
unit_price 0
discount 0
region 0
payment_method 0
rating 0
total_amount 0
基本统计信息:
quantity unit_price discount total_amount rating
count 10957.0000 10957.000000 10957.0000 10957.000000 10957.0000
mean 3.0235 1589.234567 0.1023 2534.567890 3.6789
std 1.4123 1234.567890 0.1345 2123.456789 1.0234
min 1.0000 10.000000 0.0000 10.000000 1.0000
25% 2.0000 567.890000 0.0000 890.123000 3.0000
50% 3.0000 1234.560000 0.1000 1890.234000 4.0000
75% 4.0000 2345.670000 0.2000 3456.789000 5.0000
max 5.0000 5000.000000 0.3000 15000.000000 5.0000
数据清洗
检查重复值
# 检查重复订单
duplicate_orders = df[df.duplicated(subset=['order_id'], keep=False)]
print(f"重复订单数:{len(duplicate_orders)}")
# 删除重复值
df = df.drop_duplicates(subset=['order_id'], keep='first')
print(f"删除重复后数据量:{len(df)}")
处理异常值
import matplotlib.pyplot as plt
# 检测价格异常值
Q1 = df['unit_price'].quantile(0.25)
Q3 = df['unit_price'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['unit_price'] < lower_bound) | (df['unit_price'] > upper_bound)]
print(f"价格异常值数量:{len(outliers)}")
print(f"异常值价格范围:{outliers['unit_price'].min()} - {outliers['unit_price'].max()}")
# 可视化异常值
plt.figure(figsize=(10, 6))
plt.boxplot(df['unit_price'], vert=False)
plt.xlabel('单价')
plt.title('商品价格箱线图')
plt.show()
处理缺失值
# 虽然我们的示例数据没有缺失值,但实际工作中经常会遇到
# 以下是常见的处理方法:
# 1. 删除含有缺失值的行
# df = df.dropna()
# 2. 用均值填充数值列
# df['unit_price'] = df['unit_price'].fillna(df['unit_price'].mean())
# 3. 用众数填充分类列
# df['region'] = df['region'].fillna(df['region'].mode()[0])
# 4. 用前向填充(适合时间序列)
# df = df.fillna(method='ffill')
# 5. 用后向填充
# df = df.fillna(method='bfill')
数据格式转换
# 确保日期格式正确
df['order_date'] = pd.to_datetime(df['order_date'])
# 提取时间特征
df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['day'] = df['order_date'].dt.day
df['weekday'] = df['order_date'].dt.weekday # 0=周一,6=周日
df['quarter'] = df['order_date'].dt.quarter
df['week'] = df['order_date'].dt.isocalendar().week
# 创建时间段标签
def get_time_period(hour):
if 6 <= hour < 12:
return '早晨'
elif 12 <= hour < 14:
return '中午'
elif 14 <= hour < 18:
return '下午'
elif 18 <= hour < 22:
return '晚上'
else:
return '深夜'
# 添加订单时间段(示例,实际需要小时数据)
df['time_period'] = '白天' # 简化示例
print("数据清洗完成!")
print(f"最终数据量:{len(df)} 条记录")
数据分析
销售概览
# 总销售额
total_sales = df['total_amount'].sum()
print(f"总销售额:¥{total_sales:,.2f}")
# 总订单数
total_orders = len(df)
print(f"总订单数:{total_orders:,}")
# 平均订单金额
avg_order = df['total_amount'].mean()
print(f"平均订单金额:¥{avg_order:,.2f}")
# 客户总数
total_customers = df['customer_id'].nunique()
print(f"客户总数:{total_customers:,}")
# 人均消费
avg_customer = total_sales / total_customers
print(f"人均消费:¥{avg_customer:,.2f}")
按类别分析
# 各类别销售统计
category_stats = df.groupby('category').agg({
'total_amount': ['sum', 'mean', 'count'],
'quantity': 'sum',
'customer_id': 'nunique'
}).round(2)
category_stats.columns = ['销售总额', '平均订单', '订单数', '销售数量', '客户数']
category_stats['销售占比'] = (category_stats['销售总额'] / category_stats['销售总额'].sum() * 100).round(2)
print("\n=== 各类别销售统计 ===")
print(category_stats.sort_values('销售总额', ascending=False))
输出示例:
=== 各类别销售统计 ===
销售总额 平均订单 订单数 销售数量 客户数 销售占比
电子产品 15234567.89 2345.67 6500 12345 4532 45.23%
服装 8765432.10 567.89 15432 45678 8765 26.01%
家居 4567890.12 345.67 13210 34567 6543 13.55%
食品 3456789.01 123.45 28000 89012 9876 10.25%
图书 1678901.23 67.89 24715 56789 8901 4.98%
按地区分析
# 各地区销售统计
region_stats = df.groupby('region').agg({
'total_amount': ['sum', 'mean'],
'order_id': 'count',
'customer_id': 'nunique'
}).round(2)
region_stats.columns = ['销售总额', '平均订单', '订单数', '客户数']
region_stats['人均消费'] = (region_stats['销售总额'] / region_stats['客户数']).round(2)
print("\n=== 各地区销售统计 ===")
print(region_stats.sort_values('销售总额', ascending=False))
按月趋势分析
# 月度销售趋势
monthly_sales = df.groupby(['year', 'month']).agg({
'total_amount': 'sum',
'order_id': 'count'
}).reset_index()
monthly_sales['年月'] = monthly_sales['year'].astype(str) + '-' + monthly_sales['month'].astype(str).str.zfill(2)
print("\n=== 月度销售趋势 ===")
print(monthly_sales[['年月', 'total_amount', 'order_id']].to_string(index=False))
支付方式分析
# 支付方式统计
payment_stats = df.groupby('payment_method').agg({
'total_amount': 'sum',
'order_id': 'count'
}).reset_index()
payment_stats.columns = ['支付方式', '销售总额', '订单数']
payment_stats['占比'] = (payment_stats['订单数'] / payment_stats['订单数'].sum() * 100).round(2)
print("\n=== 支付方式统计 ===")
print(payment_stats.sort_values('订单数', ascending=False))
客户分析
# 客户价值分析
customer_stats = df.groupby('customer_id').agg({
'total_amount': ['sum', 'mean', 'count'],
'category': 'nunique'
}).reset_index()
customer_stats.columns = ['客户 ID', '总消费', '平均订单', '订单数', '购买类别数']
# RFM 分析基础
print("\n=== 客户价值 TOP 10 ===")
print(customer_stats.sort_values('总消费', ascending=False).head(10))
# 客户分层
def customer_level(avg_order):
if avg_order >= 2000:
return 'VIP 客户'
elif avg_order >= 1000:
return '重要客户'
elif avg_order >= 500:
return '普通客户'
else:
return '潜在客户'
customer_stats['客户等级'] = customer_stats['平均订单'].apply(customer_level)
level_dist = customer_stats['客户等级'].value_counts()
print("\n=== 客户等级分布 ===")
print(level_dist)
数据可视化
设置绘图风格
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# 设置 seaborn 风格
sns.set_style("whitegrid")
sns.set_palette("husl")
销售趋势图
# 月度销售趋势
fig, axes = plt.subplots(2, 1, figsize=(14, 10))
# 销售额趋势
ax1 = axes[0]
monthly = df.groupby(df['order_date'].dt.to_period('M'))['total_amount'].sum()
ax1.plot(monthly.index.astype(str), monthly.values, marker='o', linewidth=2, markersize=6)
ax1.set_title('2024 年月度销售额趋势', fontsize=16, fontweight='bold')
ax1.set_xlabel('月份', fontsize=12)
ax1.set_ylabel('销售额 (元)', fontsize=12)
ax1.grid(True, alpha=0.3)
ax1.tick_params(axis='x', rotation=45)
# 添加数据标签
for i, v in enumerate(monthly.values):
ax1.annotate(f'{v/10000:.1f}万', (i, v), ha='center', va='bottom', fontsize=9)
# 订单数量趋势
ax2 = axes[1]
orders_monthly = df.groupby(df['order_date'].dt.to_period('M'))['order_id'].count()
ax2.bar(orders_monthly.index.astype(str), orders_monthly.values, color='skyblue', alpha=0.7)
ax2.set_title('2024 年月度订单数量趋势', fontsize=16, fontweight='bold')
ax2.set_xlabel('月份', fontsize=12)
ax2.set_ylabel('订单数', fontsize=12)
ax2.tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.savefig('sales_trend.png', dpi=300, bbox_inches='tight')
plt.show()
类别销售占比
# 饼图
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
# 销售额占比
ax1 = axes[0]
category_sales = df.groupby('category')['total_amount'].sum()
colors = plt.cm.Set3(np.linspace(0, 1, len(category_sales)))
wedges, texts, autotexts = ax1.pie(category_sales.values, labels=category_sales.index,
autopct='%1.1f%%', colors=colors, startangle=90)
ax1.set_title('各类别销售额占比', fontsize=16, fontweight='bold')
# 设置字体
for text in texts:
text.set_fontsize(11)
for autotext in autotexts:
autotext.set_fontsize(10)
autotext.set_color('white')
# 订单数量占比
ax2 = axes[1]
category_orders = df.groupby('category')['order_id'].count()
colors2 = plt.cm.Pastel1(np.linspace(0, 1, len(category_orders)))
wedges2, texts2, autotexts2 = ax2.pie(category_orders.values, labels=category_orders.index,
autopct='%1.1f%%', colors=colors2, startangle=90)
ax2.set_title('各类别订单数量占比', fontsize=16, fontweight='bold')
for text in texts2:
text.set_fontsize(11)
for autotext in autotexts2:
autotext.set_fontsize(10)
autotext.set_color('black')
plt.tight_layout()
plt.savefig('category_pie.png', dpi=300, bbox_inches='tight')
plt.show()
地区销售热力图
# 地区 - 类别热力图
pivot_data = df.pivot_table(values='total_amount', index='region',
columns='category', aggfunc='sum')
plt.figure(figsize=(12, 8))
sns.heatmap(pivot_data, annot=True, fmt='.0f', cmap='YlOrRd',
linewidths=0.5, linecolor='gray')
plt.title('各地区 - 各类别销售热力图', fontsize=16, fontweight='bold')
plt.xlabel('产品类别', fontsize=12)
plt.ylabel('地区', fontsize=12)
plt.tight_layout()
plt.savefig('region_heatmap.png', dpi=300, bbox_inches='tight')
plt.show()
客户分布直方图
# 客户消费分布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 客户总消费分布
ax1 = axes[0, 0]
customer_total = df.groupby('customer_id')['total_amount'].sum()
ax1.hist(customer_total, bins=50, color='steelblue', alpha=0.7, edgecolor='black')
ax1.set_title('客户总消费分布', fontsize=14, fontweight='bold')
ax1.set_xlabel('消费金额 (元)', fontsize=12)
ax1.set_ylabel('客户数', fontsize=12)
ax1.axvline(customer_total.mean(), color='red', linestyle='--', label=f'平均值:¥{customer_total.mean():.2f}')
ax1.legend()
# 订单数量分布
ax2 = axes[0, 1]
customer_orders = df.groupby('customer_id')['order_id'].count()
ax2.hist(customer_orders, bins=30, color='coral', alpha=0.7, edgecolor='black')
ax2.set_title('客户订单数量分布', fontsize=14, fontweight='bold')
ax2.set_xlabel('订单数', fontsize=12)
ax2.set_ylabel('客户数', fontsize=12)
ax2.axvline(customer_orders.mean(), color='red', linestyle='--', label=f'平均值:{customer_orders.mean():.1f}')
ax2.legend()
# 评分分布
ax3 = axes[1, 0]
rating_dist = df['rating'].value_counts().sort_index()
ax3.bar(rating_dist.index, rating_dist.values, color='green', alpha=0.7, edgecolor='black')
ax3.set_title('客户评分分布', fontsize=14, fontweight='bold')
ax3.set_xlabel('评分', fontsize=12)
ax3.set_ylabel('数量', fontsize=12)
ax3.set_xticks([1, 2, 3, 4, 5])
# 折扣使用分布
ax4 = axes[1, 1]
discount_dist = df['discount'].value_counts().sort_index()
ax4.bar([f'{d*100:.0f}%' for d in discount_dist.index], discount_dist.values,
color='purple', alpha=0.7, edgecolor='black')
ax4.set_title('折扣使用分布', fontsize=14, fontweight='bold')
ax4.set_xlabel('折扣率', fontsize=12)
ax4.set_ylabel('订单数', fontsize=12)
plt.tight_layout()
plt.savefig('customer_distribution.png', dpi=300, bbox_inches='tight')
plt.show()
相关性热力图
# 数值变量相关性分析
corr_cols = ['quantity', 'unit_price', 'discount', 'total_amount', 'rating']
corr_matrix = df[corr_cols].corr()
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='coolwarm',
square=True, linewidths=0.5, center=0,
xticklabels=['数量', '单价', '折扣', '总金额', '评分'],
yticklabels=['数量', '单价', '折扣', '总金额', '评分'])
plt.title('变量相关性热力图', fontsize=16, fontweight='bold')
plt.tight_layout()
plt.savefig('correlation_heatmap.png', dpi=300, bbox_inches='tight')
plt.show()
print("\n=== 相关性分析 ===")
print(corr_matrix.round(3))
实战项目
项目一:销售预测
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 准备数据 - 按日期聚合
daily_sales = df.groupby('order_date').agg({
'total_amount': 'sum',
'order_id': 'count'
}).reset_index()
daily_sales.columns = ['date', 'sales', 'orders']
# 创建时间特征
daily_sales['day_of_week'] = daily_sales['date'].dt.dayofweek
daily_sales['month'] = daily_sales['date'].dt.month
daily_sales['day'] = daily_sales['date'].dt.day
# 创建滞后特征
daily_sales['sales_lag1'] = daily_sales['sales'].shift(1)
daily_sales['sales_lag7'] = daily_sales['sales'].shift(7)
daily_sales['sales_rolling7'] = daily_sales['sales'].rolling(7).mean()
# 删除 NaN 值
daily_sales = daily_sales.dropna()
# 特征和目标
X = daily_sales[['day_of_week', 'month', 'day', 'sales_lag1', 'sales_lag7', 'sales_rolling7']]
y = daily_sales['sales']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练模型
model = LinearRegression()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 评估
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"=== 销售预测模型评估 ===")
print(f"均方误差 (MSE): {mse:.2f}")
print(f"R² 分数:{r2:.4f}")
print(f"\n特征重要性:")
for feature, coef in zip(X.columns, model.coef_):
print(f" {feature}: {coef:.2f}")
# 可视化预测结果
plt.figure(figsize=(14, 6))
plt.plot(y_test.values, label='实际销售额', linewidth=2)
plt.plot(y_pred, label='预测销售额', linewidth=2, alpha=0.7)
plt.title('销售预测 vs 实际销售', fontsize=16, fontweight='bold')
plt.xlabel('样本索引', fontsize=12)
plt.ylabel('销售额 (元)', fontsize=12)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
项目二:客户分群
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# 准备客户特征数据
customer_features = df.groupby('customer_id').agg({
'total_amount': ['sum', 'mean', 'count'],
'rating': 'mean',
'category': 'nunique'
}).reset_index()
customer_features.columns = ['customer_id', 'total_spent', 'avg_order',
'order_count', 'avg_rating', 'category_count']
# 特征缩放
scaler = StandardScaler()
features_scaled = scaler.fit_transform(customer_features[['total_spent', 'avg_order',
'order_count', 'avg_rating',
'category_count']])
# K-Means 聚类
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
customer_features['cluster'] = kmeans.fit_predict(features_scaled)
# 分析各集群特征
cluster_profile = customer_features.groupby('cluster').agg({
'total_spent': 'mean',
'avg_order': 'mean',
'order_count': 'mean',
'avg_rating': 'mean',
'category_count': 'mean',
'customer_id': 'count'
}).round(2)
cluster_profile.columns = ['平均总消费', '平均订单', '平均订单数', '平均评分',
'平均类别数', '客户数']
print("\n=== 客户分群画像 ===")
print(cluster_profile)
# 可视化分群结果
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 各集群客户数和平均消费
ax1 = axes[0, 0]
cluster_counts = customer_features['cluster'].value_counts().sort_index()
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A']
bars = ax1.bar(cluster_counts.index, cluster_counts.values, color=colors)
ax1.set_title('各集群客户数量', fontsize=14, fontweight='bold')
ax1.set_xlabel('集群编号', fontsize=12)
ax1.set_ylabel('客户数', fontsize=12)
for bar, count in zip(bars, cluster_counts.values):
ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 50,
str(count), ha='center', va='bottom', fontsize=11)
# 雷达图 - 各集群特征
ax2 = axes[0, 1]
categories = ['总消费', '订单均价', '订单数', '评分', '类别数']
angles = np.linspace(0, 2 * np.pi, len(categories), endpoint=False).tolist()
angles += angles[:1]
for cluster in range(4):
cluster_data = customer_features[customer_features['cluster'] == cluster]
values = cluster_data[['total_spent', 'avg_order', 'order_count',
'avg_rating', 'category_count']].mean().values
# 归一化
values = values / values.max()
values = values.tolist()
values += values[:1]
ax2.plot(angles, values, 'o-', linewidth=2, label=f'集群{cluster}', color=colors[cluster])
ax2.fill(angles, values, alpha=0.15, color=colors[cluster])
ax2.set_xticks(angles[:-1])
ax2.set_xticklabels(categories, fontsize=10)
ax2.set_title('各集群特征雷达图', fontsize=14, fontweight='bold')
ax2.legend(loc='upper right', bbox_to_anchor=(1.3, 1))
ax2.grid(True, alpha=0.3)
# 集群 0 vs 集群 1 对比
ax3 = axes[1, 0]
cluster_0 = customer_features[customer_features['cluster'] == 0]['total_spent']
cluster_1 = customer_features[customer_features['cluster'] == 1]['total_spent']
ax3.boxplot([cluster_0, cluster_1], labels=['集群 0', '集群 1'], patch_artist=True,
boxprops=dict(facecolor='lightblue'),
medianprops=dict(color='red'))
ax3.set_title('集群 0 vs 集群 1 - 总消费对比', fontsize=14, fontweight='bold')
ax3.set_ylabel('总消费 (元)', fontsize=12)
# 订单数分布
ax4 = axes[1, 1]
for cluster in range(4):
cluster_data = customer_features[customer_features['cluster'] == cluster]
ax4.hist(cluster_data['order_count'], alpha=0.5, label=f'集群{cluster}',
bins=20, color=colors[cluster])
ax4.set_title('各集群订单数分布', fontsize=14, fontweight='bold')
ax4.set_xlabel('订单数', fontsize=12)
ax4.set_ylabel('客户数', fontsize=12)
ax4.legend()
plt.tight_layout()
plt.savefig('customer_clustering.png', dpi=300, bbox_inches='tight')
plt.show()
项目三:构建数据分析报告
# 生成数据分析报告
report = f"""
# 电商销售数据分析报告
## 一、数据概览
- **数据时间范围**: {df['order_date'].min().strftime('%Y-%m-%d')} 至 {df['order_date'].max().strftime('%Y-%m-%d')}
- **总记录数**: {len(df):,} 条
- **总销售额**: ¥{df['total_amount'].sum():,.2f}
- **总订单数**: {len(df):,}
- **客户总数**: {df['customer_id'].nunique():,}
## 二、核心指标
| 指标 | 数值 |
|------|------|
| 平均订单金额 | ¥{df['total_amount'].mean():,.2f} |
| 人均消费 | ¥{df.groupby('customer_id')['total_amount'].sum().mean():,.2f} |
| 最高单笔订单 | ¥{df['total_amount'].max():,.2f} |
| 平均评分 | {df['rating'].mean():.2f} / 5.0 |
## 三、销售排名
### 按产品类别
"""
# 添加类别排名
category_rank = df.groupby('category')['total_amount'].sum().sort_values(ascending=False)
for i, (cat, sales) in enumerate(category_rank.items(), 1):
report += f"{i}. **{cat}**: ¥{sales:,.2f}\n"
report += f"""
### 按地区
"""
# 添加地区排名
region_rank = df.groupby('region')['total_amount'].sum().sort_values(ascending=False)
for i, (reg, sales) in enumerate(region_rank.items(), 1):
report += f"{i}. **{reg}**: ¥{sales:,.2f}\n"
report += f"""
## 四、关键发现
1. **销售主力**: {category_rank.index[0]} 是销售额最高的类别,占比 {category_rank.iloc[0]/category_rank.sum()*100:.1f}%
2. **核心市场**: {region_rank.index[0]} 地区贡献了最大销售额
3. **客户价值**: 前 10% 的客户贡献了总销售额的约 40%
4. **支付偏好**: 支付宝是最受欢迎的支付方式
## 五、建议
1. 加大对 {category_rank.index[0]} 类别的营销投入
2. 在 {region_rank.index[0]} 地区开展更多促销活动
3. 推出 VIP 会员计划,提升高价值客户留存
4. 优化其他支付方式的用户体验
---
*报告生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*
"""
# 保存报告
with open('sales_analysis_report.md', 'w', encoding='utf-8') as f:
f.write(report)
print("数据分析报告已生成:sales_analysis_report.md")
print("\n" + "="*50)
print(report)
总结与进阶
本教程涵盖的技能
| 技能领域 | 具体内容 |
|---|---|
| 环境搭建 | Python、虚拟环境、依赖管理 |
| 数据处理 | Pandas 基础、数据清洗、格式转换 |
| 数据探索 | 描述性统计、分组聚合、透视表 |
| 数据可视化 | Matplotlib、Seaborn、图表美化 |
| 机器学习 | 线性回归、K-Means 聚类 |
| 报告撰写 | Markdown 报告、数据故事 |
进阶学习路线
入门 → 进阶 → 高级
↓ ↓ ↓
Pandas 时间序列 深度学习
NumPy 统计检验 大规模数据
Matplotlib 机器学习 分布式计算
Seaborn 特征工程 模型部署
推荐学习资源
书籍:
- 《利用 Python 进行数据分析》- Wes McKinney
- 《Python 数据科学手册》- Jake VanderPlas
- 《统计学习方法》- 李航
在线课程:
- Coursera: Applied Data Science with Python
- edX: Data Science MicroMasters
- Kaggle: Python/Pandas/Machine Learning 教程
实践平台:
- Kaggle: 数据科学竞赛和数据集
- 天池:阿里云数据竞赛平台
- UCI Machine Learning Repository: 经典数据集
下一步学习建议
- 深入学习 Pandas:掌握更高级的数据操作技巧
- 学习时间序列分析:ARIMA、Prophet 等预测模型
- 掌握更多可视化库:Plotly、Bokeh 等交互式图表
- 实践真实项目:从 Kaggle 或工作中找实际数据
- 建立作品集:在 GitHub 上分享你的分析项目
附录:完整代码
本教程的完整代码和数据集已上传至 GitHub:
# 克隆项目
git clone https://github.com/yourusername/ecommerce-analysis.git
# 进入项目目录
cd ecommerce-analysis
# 安装依赖
pip install -r requirements.txt
# 运行分析
jupyter notebook ecommerce_analysis.ipynb
教程结束!希望这份指南能帮助你开启 Python 数据分析之旅。如有问题,欢迎在评论区留言讨论。