📊 引言

在大数据时代,数据分析已经成为各行各业不可或缺的技能。Python凭借其丰富的数据科学生态系统,成为了数据分析师和数据科学家的首选工具。本文将通过一个完整的实战项目,带你掌握Python数据分析的核心技能。

🛠️ 环境准备

核心库安装

1
2
3
4
5
6
7
8
9
10
11
# 创建虚拟环境
python -m venv data_analysis_env
source data_analysis_env/bin/activate # Linux/Mac
# data_analysis_env\Scripts\activate # Windows

# 安装核心数据分析库
pip install pandas numpy matplotlib seaborn plotly
pip install scikit-learn scipy statsmodels
pip install jupyter notebook ipython
pip install requests beautifulsoup4 # 数据获取
pip install openpyxl xlrd # Excel文件处理

导入必要的库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 数据处理和分析
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')

# 数据可视化
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 统计分析
from scipy import stats
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler

# 设置中文字体和样式
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")
sns.set_palette("husl")

print("环境准备完成!")

📈 实战项目:电商销售数据分析

项目背景

我们将分析一个电商平台的销售数据,目标是:

  1. 了解销售趋势和季节性模式
  2. 分析产品类别和地区的销售表现
  3. 识别高价值客户群体
  4. 预测未来销售趋势

1. 数据获取与加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 生成模拟电商数据
def generate_ecommerce_data(n_records=10000):
"""生成模拟电商销售数据"""
np.random.seed(42)

# 时间范围:2022-01-01 到 2024-10-29
start_date = datetime(2022, 1, 1)
end_date = datetime(2024, 10, 29)
date_range = pd.date_range(start_date, end_date, freq='D')

data = []
customer_ids = range(1, 2001) # 2000个客户
product_categories = ['电子产品', '服装', '家居用品', '图书', '运动用品', '美妆护肤']
regions = ['华北', '华东', '华南', '华中', '西南', '西北', '东北']

for i in range(n_records):
# 随机选择日期,但增加一些季节性趋势
date = np.random.choice(date_range)
month = date.month

# 季节性调整(夏季和年底销售更好)
seasonal_factor = 1.0
if month in [6, 7, 8]: # 夏季
seasonal_factor = 1.3
elif month in [11, 12]: # 年底
seasonal_factor = 1.5

# 生成订单数据
order_data = {
'order_id': f'ORD{i+1:06d}',
'customer_id': np.random.choice(customer_ids),
'order_date': date,
'product_category': np.random.choice(product_categories),
'region': np.random.choice(regions),
'quantity': np.random.randint(1, 6),
'unit_price': np.random.uniform(50, 500) * seasonal_factor,
'discount_rate': np.random.uniform(0, 0.3),
}

# 计算总金额
order_data['total_amount'] = (
order_data['quantity'] *
order_data['unit_price'] *
(1 - order_data['discount_rate'])
)

data.append(order_data)

return pd.DataFrame(data)

# 生成数据
print("正在生成模拟数据...")
df = generate_ecommerce_data(10000)
print(f"数据生成完成,共 {len(df)} 条记录")

# 数据基本信息
print("\n数据基本信息:")
print(df.info())
print("\n数据前5行:")
print(df.head())

2. 数据探索与清洗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class DataExplorer:
"""数据探索和清洗工具类"""

def __init__(self, data):
self.data = data.copy()
self.original_shape = data.shape

def basic_info(self):
"""基本信息统计"""
print("=" * 50)
print("数据基本信息")
print("=" * 50)
print(f"数据形状: {self.data.shape}")
print(f"内存使用: {self.data.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
print("\n数据类型:")
print(self.data.dtypes)

print("\n缺失值统计:")
missing_data = self.data.isnull().sum()
missing_percent = (missing_data / len(self.data)) * 100
missing_df = pd.DataFrame({
'缺失数量': missing_data,
'缺失比例(%)': missing_percent
})
print(missing_df[missing_df['缺失数量'] > 0])

def numerical_summary(self):
"""数值型变量描述性统计"""
print("\n" + "=" * 50)
print("数值型变量描述性统计")
print("=" * 50)
numerical_cols = self.data.select_dtypes(include=[np.number]).columns
print(self.data[numerical_cols].describe())

def categorical_summary(self):
"""分类变量统计"""
print("\n" + "=" * 50)
print("分类变量统计")
print("=" * 50)
categorical_cols = self.data.select_dtypes(include=['object']).columns

for col in categorical_cols:
if col != 'order_id': # 跳过订单ID
print(f"\n{col} 分布:")
value_counts = self.data[col].value_counts()
print(value_counts.head(10))

def detect_outliers(self, columns=None):
"""异常值检测"""
if columns is None:
columns = self.data.select_dtypes(include=[np.number]).columns

print("\n" + "=" * 50)
print("异常值检测 (IQR方法)")
print("=" * 50)

outliers_info = {}
for col in columns:
Q1 = self.data[col].quantile(0.25)
Q3 = self.data[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

outliers = self.data[(self.data[col] < lower_bound) |
(self.data[col] > upper_bound)]

outliers_info[col] = {
'count': len(outliers),
'percentage': len(outliers) / len(self.data) * 100,
'lower_bound': lower_bound,
'upper_bound': upper_bound
}

print(f"{col}: {len(outliers)} 个异常值 ({len(outliers)/len(self.data)*100:.2f}%)")

return outliers_info

def clean_data(self):
"""数据清洗"""
print("\n" + "=" * 50)
print("开始数据清洗")
print("=" * 50)

# 转换日期类型
self.data['order_date'] = pd.to_datetime(self.data['order_date'])

# 添加时间特征
self.data['year'] = self.data['order_date'].dt.year
self.data['month'] = self.data['order_date'].dt.month
self.data['day_of_week'] = self.data['order_date'].dt.dayofweek
self.data['quarter'] = self.data['order_date'].dt.quarter

# 处理异常值(这里采用保守策略,只处理明显错误的数据)
# 删除数量为0或负数的记录
before_count = len(self.data)
self.data = self.data[self.data['quantity'] > 0]
self.data = self.data[self.data['unit_price'] > 0]
self.data = self.data[self.data['total_amount'] > 0]
after_count = len(self.data)

print(f"删除异常记录: {before_count - after_count} 条")
print(f"清洗后数据形状: {self.data.shape}")

return self.data

# 执行数据探索和清洗
explorer = DataExplorer(df)
explorer.basic_info()
explorer.numerical_summary()
explorer.categorical_summary()
outliers = explorer.detect_outliers(['quantity', 'unit_price', 'total_amount'])
cleaned_data = explorer.clean_data()

3. 探索性数据分析 (EDA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
class EDAAnalyzer:
"""探索性数据分析工具类"""

def __init__(self, data):
self.data = data

def sales_trend_analysis(self):
"""销售趋势分析"""
# 按日期聚合销售数据
daily_sales = self.data.groupby('order_date').agg({
'total_amount': 'sum',
'order_id': 'count'
}).rename(columns={'order_id': 'order_count'})

# 按月聚合
monthly_sales = self.data.groupby([self.data['order_date'].dt.to_period('M')]).agg({
'total_amount': 'sum',
'order_id': 'count'
}).rename(columns={'order_id': 'order_count'})

# 创建图表
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('销售趋势分析', fontsize=16, fontweight='bold')

# 日销售额趋势
axes[0, 0].plot(daily_sales.index, daily_sales['total_amount'], alpha=0.7)
axes[0, 0].set_title('日销售额趋势')
axes[0, 0].set_ylabel('销售额')
axes[0, 0].tick_params(axis='x', rotation=45)

# 月销售额趋势
monthly_sales.index = monthly_sales.index.to_timestamp()
axes[0, 1].plot(monthly_sales.index, monthly_sales['total_amount'],
marker='o', linewidth=2)
axes[0, 1].set_title('月销售额趋势')
axes[0, 1].set_ylabel('销售额')
axes[0, 1].tick_params(axis='x', rotation=45)

# 季度销售对比
quarterly_sales = self.data.groupby(['year', 'quarter'])['total_amount'].sum().reset_index()
quarterly_sales['year_quarter'] = quarterly_sales['year'].astype(str) + 'Q' + quarterly_sales['quarter'].astype(str)

axes[1, 0].bar(quarterly_sales['year_quarter'], quarterly_sales['total_amount'])
axes[1, 0].set_title('季度销售额对比')
axes[1, 0].set_ylabel('销售额')
axes[1, 0].tick_params(axis='x', rotation=45)

# 星期几销售模式
weekday_sales = self.data.groupby('day_of_week')['total_amount'].sum()
weekday_names = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']

axes[1, 1].bar(weekday_names, weekday_sales.values)
axes[1, 1].set_title('星期几销售模式')
axes[1, 1].set_ylabel('销售额')

plt.tight_layout()
plt.show()

return daily_sales, monthly_sales

def category_analysis(self):
"""产品类别分析"""
# 按类别统计
category_stats = self.data.groupby('product_category').agg({
'total_amount': ['sum', 'mean', 'count'],
'quantity': 'sum'
}).round(2)

category_stats.columns = ['总销售额', '平均订单金额', '订单数量', '总销量']
category_stats = category_stats.sort_values('总销售额', ascending=False)

# 创建可视化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('产品类别分析', fontsize=16, fontweight='bold')

# 销售额饼图
axes[0, 0].pie(category_stats['总销售额'], labels=category_stats.index,
autopct='%1.1f%%', startangle=90)
axes[0, 0].set_title('各类别销售额占比')

# 订单数量柱状图
axes[0, 1].bar(category_stats.index, category_stats['订单数量'])
axes[0, 1].set_title('各类别订单数量')
axes[0, 1].tick_params(axis='x', rotation=45)

# 平均订单金额
axes[1, 0].bar(category_stats.index, category_stats['平均订单金额'])
axes[1, 0].set_title('各类别平均订单金额')
axes[1, 0].tick_params(axis='x', rotation=45)

# 总销量
axes[1, 1].bar(category_stats.index, category_stats['总销量'])
axes[1, 1].set_title('各类别总销量')
axes[1, 1].tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

print("产品类别统计:")
print(category_stats)

return category_stats

def regional_analysis(self):
"""地区分析"""
regional_stats = self.data.groupby('region').agg({
'total_amount': ['sum', 'mean'],
'order_id': 'count',
'customer_id': 'nunique'
}).round(2)

regional_stats.columns = ['总销售额', '平均订单金额', '订单数量', '客户数量']
regional_stats = regional_stats.sort_values('总销售额', ascending=False)

# 可视化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('地区销售分析', fontsize=16, fontweight='bold')

# 各地区销售额
axes[0, 0].bar(regional_stats.index, regional_stats['总销售额'])
axes[0, 0].set_title('各地区总销售额')
axes[0, 0].tick_params(axis='x', rotation=45)

# 各地区客户数量
axes[0, 1].bar(regional_stats.index, regional_stats['客户数量'])
axes[0, 1].set_title('各地区客户数量')
axes[0, 1].tick_params(axis='x', rotation=45)

# 平均订单金额对比
axes[1, 0].bar(regional_stats.index, regional_stats['平均订单金额'])
axes[1, 0].set_title('各地区平均订单金额')
axes[1, 0].tick_params(axis='x', rotation=45)

# 地区销售额占比饼图
axes[1, 1].pie(regional_stats['总销售额'], labels=regional_stats.index,
autopct='%1.1f%%', startangle=90)
axes[1, 1].set_title('各地区销售额占比')

plt.tight_layout()
plt.show()

print("地区销售统计:")
print(regional_stats)

return regional_stats

def customer_analysis(self):
"""客户分析"""
customer_stats = self.data.groupby('customer_id').agg({
'total_amount': ['sum', 'mean', 'count'],
'order_date': ['min', 'max']
}).round(2)

customer_stats.columns = ['总消费金额', '平均订单金额', '订单次数', '首次购买', '最后购买']

# 计算客户生命周期
customer_stats['购买周期(天)'] = (
customer_stats['最后购买'] - customer_stats['首次购买']
).dt.days

# 客户分层
def classify_customer(row):
if row['总消费金额'] >= customer_stats['总消费金额'].quantile(0.8):
return '高价值客户'
elif row['总消费金额'] >= customer_stats['总消费金额'].quantile(0.5):
return '中价值客户'
else:
return '低价值客户'

customer_stats['客户类型'] = customer_stats.apply(classify_customer, axis=1)

# 可视化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('客户分析', fontsize=16, fontweight='bold')

# 客户消费金额分布
axes[0, 0].hist(customer_stats['总消费金额'], bins=50, alpha=0.7)
axes[0, 0].set_title('客户消费金额分布')
axes[0, 0].set_xlabel('总消费金额')
axes[0, 0].set_ylabel('客户数量')

# 客户订单次数分布
axes[0, 1].hist(customer_stats['订单次数'], bins=30, alpha=0.7)
axes[0, 1].set_title('客户订单次数分布')
axes[0, 1].set_xlabel('订单次数')
axes[0, 1].set_ylabel('客户数量')

# 客户类型分布
customer_type_counts = customer_stats['客户类型'].value_counts()
axes[1, 0].pie(customer_type_counts.values, labels=customer_type_counts.index,
autopct='%1.1f%%', startangle=90)
axes[1, 0].set_title('客户类型分布')

# 客户价值散点图
axes[1, 1].scatter(customer_stats['订单次数'], customer_stats['总消费金额'], alpha=0.6)
axes[1, 1].set_title('客户价值分析')
axes[1, 1].set_xlabel('订单次数')
axes[1, 1].set_ylabel('总消费金额')

plt.tight_layout()
plt.show()

# 打印客户统计信息
print("客户统计信息:")
print(f"总客户数: {len(customer_stats)}")
print(f"平均客户价值: {customer_stats['总消费金额'].mean():.2f}")
print(f"客户价值中位数: {customer_stats['总消费金额'].median():.2f}")
print("\n客户类型分布:")
print(customer_type_counts)

return customer_stats

# 执行EDA分析
eda = EDAAnalyzer(cleaned_data)
daily_sales, monthly_sales = eda.sales_trend_analysis()
category_stats = eda.category_analysis()
regional_stats = eda.regional_analysis()
customer_stats = eda.customer_analysis()

4. 高级分析与建模

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
class AdvancedAnalyzer:
"""高级分析工具类"""

def __init__(self, data):
self.data = data

def correlation_analysis(self):
"""相关性分析"""
# 选择数值型变量
numerical_cols = ['quantity', 'unit_price', 'discount_rate', 'total_amount',
'year', 'month', 'day_of_week', 'quarter']

correlation_matrix = self.data[numerical_cols].corr()

# 热力图可视化
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0,
square=True, linewidths=0.5)
plt.title('变量相关性热力图')
plt.tight_layout()
plt.show()

return correlation_matrix

def seasonal_decomposition(self):
"""季节性分解"""
from statsmodels.tsa.seasonal import seasonal_decompose

# 准备时间序列数据
daily_sales = self.data.groupby('order_date')['total_amount'].sum()
daily_sales = daily_sales.asfreq('D', fill_value=0) # 填充缺失日期

# 季节性分解
decomposition = seasonal_decompose(daily_sales, model='additive', period=30)

# 可视化
fig, axes = plt.subplots(4, 1, figsize=(15, 12))
fig.suptitle('销售数据季节性分解', fontsize=16, fontweight='bold')

decomposition.observed.plot(ax=axes[0], title='原始数据')
decomposition.trend.plot(ax=axes[1], title='趋势')
decomposition.seasonal.plot(ax=axes[2], title='季节性')
decomposition.resid.plot(ax=axes[3], title='残差')

plt.tight_layout()
plt.show()

return decomposition

def sales_prediction_model(self):
"""销售预测模型"""
# 准备特征数据
feature_data = self.data.copy()

# 创建特征工程
feature_data['month_sin'] = np.sin(2 * np.pi * feature_data['month'] / 12)
feature_data['month_cos'] = np.cos(2 * np.pi * feature_data['month'] / 12)
feature_data['day_sin'] = np.sin(2 * np.pi * feature_data['day_of_week'] / 7)
feature_data['day_cos'] = np.cos(2 * np.pi * feature_data['day_of_week'] / 7)

# 对分类变量进行编码
category_encoded = pd.get_dummies(feature_data['product_category'], prefix='category')
region_encoded = pd.get_dummies(feature_data['region'], prefix='region')

# 合并特征
features = pd.concat([
feature_data[['quantity', 'unit_price', 'discount_rate',
'month_sin', 'month_cos', 'day_sin', 'day_cos']],
category_encoded,
region_encoded
], axis=1)

target = feature_data['total_amount']

# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
features, target, test_size=0.2, random_state=42
)

# 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 训练线性回归模型
model = LinearRegression()
model.fit(X_train_scaled, y_train)

# 预测
y_pred = model.predict(X_test_scaled)

# 评估模型
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print("销售预测模型评估:")
print(f"均方误差 (MSE): {mse:.2f}")
print(f"决定系数 (R²): {r2:.4f}")

# 可视化预测结果
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.scatter(y_test, y_pred, alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.xlabel('实际值')
plt.ylabel('预测值')
plt.title('预测值 vs 实际值')

plt.subplot(1, 2, 2)
residuals = y_test - y_pred
plt.scatter(y_pred, residuals, alpha=0.6)
plt.axhline(y=0, color='r', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')
plt.title('残差图')

plt.tight_layout()
plt.show()

# 特征重要性
feature_importance = pd.DataFrame({
'feature': features.columns,
'importance': abs(model.coef_)
}).sort_values('importance', ascending=False)

plt.figure(figsize=(10, 6))
top_features = feature_importance.head(10)
plt.barh(top_features['feature'], top_features['importance'])
plt.xlabel('特征重要性')
plt.title('Top 10 特征重要性')
plt.gca().invert_yaxis()
plt.tight_layout()
plt.show()

return model, scaler, feature_importance

def customer_segmentation(self):
"""客户细分分析"""
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# 准备客户特征数据
customer_features = self.data.groupby('customer_id').agg({
'total_amount': ['sum', 'mean', 'count'],
'order_date': ['min', 'max'],
'discount_rate': 'mean'
})

customer_features.columns = ['总消费', '平均消费', '购买次数', '首次购买', '最后购买', '平均折扣']

# 计算客户活跃度(距离最后购买的天数)
customer_features['最后购买距今'] = (
datetime.now() - customer_features['最后购买']
).dt.days

# 计算客户生命周期
customer_features['生命周期'] = (
customer_features['最后购买'] - customer_features['首次购买']
).dt.days + 1

# 选择聚类特征
clustering_features = ['总消费', '购买次数', '最后购买距今', '生命周期']
X = customer_features[clustering_features].fillna(0)

# 标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 确定最优聚类数量
inertias = []
K_range = range(2, 11)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(X_scaled)
inertias.append(kmeans.inertia_)

# 肘部法则图
plt.figure(figsize=(10, 6))
plt.plot(K_range, inertias, 'bo-')
plt.xlabel('聚类数量 (k)')
plt.ylabel('簇内平方和')
plt.title('肘部法则确定最优聚类数量')
plt.grid(True)
plt.show()

# 使用4个聚类
kmeans = KMeans(n_clusters=4, random_state=42)
customer_features['客户群体'] = kmeans.fit_predict(X_scaled)

# 分析各客户群体特征
segment_analysis = customer_features.groupby('客户群体')[clustering_features].mean()

print("客户群体特征分析:")
print(segment_analysis.round(2))

# 可视化客户群体
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('客户群体分析', fontsize=16, fontweight='bold')

# 总消费 vs 购买次数
scatter = axes[0, 0].scatter(customer_features['购买次数'],
customer_features['总消费'],
c=customer_features['客户群体'],
cmap='viridis', alpha=0.6)
axes[0, 0].set_xlabel('购买次数')
axes[0, 0].set_ylabel('总消费')
axes[0, 0].set_title('总消费 vs 购买次数')
plt.colorbar(scatter, ax=axes[0, 0])

# 客户群体分布
segment_counts = customer_features['客户群体'].value_counts().sort_index()
axes[0, 1].pie(segment_counts.values, labels=[f'群体{i}' for i in segment_counts.index],
autopct='%1.1f%%', startangle=90)
axes[0, 1].set_title('客户群体分布')

# 各群体平均消费
axes[1, 0].bar([f'群体{i}' for i in segment_analysis.index],
segment_analysis['总消费'])
axes[1, 0].set_title('各群体平均总消费')
axes[1, 0].set_ylabel('总消费')

# 各群体购买频次
axes[1, 1].bar([f'群体{i}' for i in segment_analysis.index],
segment_analysis['购买次数'])
axes[1, 1].set_title('各群体平均购买次数')
axes[1, 1].set_ylabel('购买次数')

plt.tight_layout()
plt.show()

return customer_features, kmeans

# 执行高级分析
advanced_analyzer = AdvancedAnalyzer(cleaned_data)
correlation_matrix = advanced_analyzer.correlation_analysis()
decomposition = advanced_analyzer.seasonal_decomposition()
model, scaler, feature_importance = advanced_analyzer.sales_prediction_model()
customer_segments, kmeans_model = advanced_analyzer.customer_segmentation()

5. 交互式可视化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
class InteractiveVisualizer:
"""交互式可视化工具类"""

def __init__(self, data):
self.data = data

def create_sales_dashboard(self):
"""创建销售仪表板"""
# 准备数据
monthly_data = self.data.groupby([
self.data['order_date'].dt.to_period('M'),
'product_category'
])['total_amount'].sum().reset_index()
monthly_data['order_date'] = monthly_data['order_date'].dt.to_timestamp()

# 创建交互式折线图
fig = px.line(monthly_data,
x='order_date',
y='total_amount',
color='product_category',
title='各产品类别月度销售趋势',
labels={'total_amount': '销售额', 'order_date': '日期'})

fig.update_layout(
xaxis_title="日期",
yaxis_title="销售额",
legend_title="产品类别",
hovermode='x unified'
)

fig.show()

def create_regional_heatmap(self):
"""创建地区热力图"""
# 按地区和月份聚合数据
regional_monthly = self.data.groupby([
'region',
self.data['order_date'].dt.to_period('M')
])['total_amount'].sum().reset_index()
regional_monthly['order_date'] = regional_monthly['order_date'].dt.to_timestamp()

# 透视表
heatmap_data = regional_monthly.pivot(
index='region',
columns='order_date',
values='total_amount'
).fillna(0)

# 创建热力图
fig = px.imshow(heatmap_data,
labels=dict(x="月份", y="地区", color="销售额"),
title="各地区月度销售热力图",
aspect="auto")

fig.update_xaxes(side="bottom")
fig.show()

def create_customer_scatter(self):
"""创建客户散点图"""
# 准备客户数据
customer_data = self.data.groupby('customer_id').agg({
'total_amount': ['sum', 'count'],
'order_date': ['min', 'max']
})

customer_data.columns = ['总消费', '订单数', '首次购买', '最后购买']
customer_data['客户ID'] = customer_data.index

# 创建散点图
fig = px.scatter(customer_data,
x='订单数',
y='总消费',
size='总消费',
hover_data=['客户ID'],
title='客户价值分析散点图',
labels={'订单数': '订单数量', '总消费': '总消费金额'})

fig.update_layout(
xaxis_title="订单数量",
yaxis_title="总消费金额"
)

fig.show()

def create_product_sunburst(self):
"""创建产品类别旭日图"""
# 按类别和地区聚合
category_region = self.data.groupby(['product_category', 'region'])['total_amount'].sum().reset_index()

fig = px.sunburst(category_region,
path=['product_category', 'region'],
values='total_amount',
title='产品类别和地区销售分布旭日图')

fig.show()

# 创建交互式可视化
visualizer = InteractiveVisualizer(cleaned_data)
visualizer.create_sales_dashboard()
visualizer.create_regional_heatmap()
visualizer.create_customer_scatter()
visualizer.create_product_sunburst()

6. 报告生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class ReportGenerator:
"""分析报告生成器"""

def __init__(self, data, analysis_results):
self.data = data
self.analysis_results = analysis_results

def generate_executive_summary(self):
"""生成执行摘要"""
total_sales = self.data['total_amount'].sum()
total_orders = len(self.data)
avg_order_value = self.data['total_amount'].mean()
unique_customers = self.data['customer_id'].nunique()

date_range = f"{self.data['order_date'].min().strftime('%Y-%m-%d')} 至 {self.data['order_date'].max().strftime('%Y-%m-%d')}"

summary = f"""
📊 电商销售数据分析报告 - 执行摘要
==========================================

📈 核心指标:
• 分析时间范围: {date_range}
• 总销售额: ¥{total_sales:,.2f}
• 总订单数: {total_orders:,}
• 平均订单价值: ¥{avg_order_value:.2f}
• 独立客户数: {unique_customers:,}

🏆 关键发现:
• 最佳销售类别: {self.data.groupby('product_category')['total_amount'].sum().idxmax()}
• 最佳销售地区: {self.data.groupby('region')['total_amount'].sum().idxmax()}
• 销售高峰月份: {self.data.groupby('month')['total_amount'].sum().idxmax()}月
• 客户复购率: {(self.data.groupby('customer_id').size() > 1).mean()*100:.1f}%

💡 业务建议:
1. 重点关注高价值客户群体的维护和扩展
2. 加强季节性营销策略,特别是在销售高峰期
3. 优化低表现地区的市场策略
4. 提升客户复购率和客户生命周期价值
"""

print(summary)
return summary

def save_analysis_results(self, filename='analysis_results.xlsx'):
"""保存分析结果到Excel"""
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
# 原始数据样本
self.data.head(1000).to_excel(writer, sheet_name='原始数据样本', index=False)

# 产品类别分析
category_stats = self.data.groupby('product_category').agg({
'total_amount': ['sum', 'mean', 'count'],
'quantity': 'sum'
}).round(2)
category_stats.columns = ['总销售额', '平均订单金额', '订单数量', '总销量']
category_stats.to_excel(writer, sheet_name='产品类别分析')

# 地区分析
regional_stats = self.data.groupby('region').agg({
'total_amount': ['sum', 'mean'],
'order_id': 'count',
'customer_id': 'nunique'
}).round(2)
regional_stats.columns = ['总销售额', '平均订单金额', '订单数量', '客户数量']
regional_stats.to_excel(writer, sheet_name='地区分析')

# 月度趋势
monthly_trend = self.data.groupby(self.data['order_date'].dt.to_period('M')).agg({
'total_amount': 'sum',
'order_id': 'count'
}).round(2)
monthly_trend.columns = ['月销售额', '月订单数']
monthly_trend.to_excel(writer, sheet_name='月度趋势')

print(f"分析结果已保存到 {filename}")

# 生成报告
report_generator = ReportGenerator(cleaned_data, {
'category_stats': category_stats,
'regional_stats': regional_stats,
'customer_stats': customer_stats
})

executive_summary = report_generator.generate_executive_summary()
report_generator.save_analysis_results('电商销售分析报告.xlsx')

🎯 最佳实践总结

1. 数据质量管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def data_quality_checklist(df):
"""数据质量检查清单"""
quality_report = {
'数据完整性': {
'总记录数': len(df),
'缺失值比例': (df.isnull().sum().sum() / (len(df) * len(df.columns))) * 100,
'重复记录数': df.duplicated().sum()
},
'数据一致性': {
'数据类型一致': df.dtypes.value_counts().to_dict(),
'异常值检测': '需要进一步分析'
},
'数据准确性': {
'数值范围检查': '需要业务规则验证',
'逻辑一致性': '需要业务规则验证'
}
}

return quality_report

# 执行数据质量检查
quality_report = data_quality_checklist(cleaned_data)
print("数据质量报告:")
for category, metrics in quality_report.items():
print(f"\n{category}:")
for metric, value in metrics.items():
print(f" {metric}: {value}")

2. 性能优化技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 大数据处理优化技巧
def optimize_dataframe_memory(df):
"""优化DataFrame内存使用"""
start_memory = df.memory_usage(deep=True).sum() / 1024**2

# 优化数值类型
for col in df.select_dtypes(include=['int64']).columns:
df[col] = pd.to_numeric(df[col], downcast='integer')

for col in df.select_dtypes(include=['float64']).columns:
df[col] = pd.to_numeric(df[col], downcast='float')

# 优化分类变量
for col in df.select_dtypes(include=['object']).columns:
if df[col].nunique() / len(df) < 0.5: # 如果唯一值比例小于50%
df[col] = df[col].astype('category')

end_memory = df.memory_usage(deep=True).sum() / 1024**2
print(f"内存优化: {start_memory:.2f}MB -> {end_memory:.2f}MB")
print(f"节省: {(start_memory - end_memory) / start_memory * 100:.1f}%")

return df

# 应用内存优化
optimized_data = optimize_dataframe_memory(cleaned_data.copy())

3. 可重用的分析模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class DataAnalysisTemplate:
"""可重用的数据分析模板"""

def __init__(self, data, target_column, date_column=None):
self.data = data
self.target_column = target_column
self.date_column = date_column

def quick_analysis(self):
"""快速分析"""
results = {}

# 基础统计
results['basic_stats'] = self.data[self.target_column].describe()

# 分布分析
results['distribution'] = {
'skewness': self.data[self.target_column].skew(),
'kurtosis': self.data[self.target_column].kurtosis()
}

# 时间趋势(如果有日期列)
if self.date_column:
time_series = self.data.groupby(self.date_column)[self.target_column].sum()
results['trend'] = {
'growth_rate': (time_series.iloc[-1] / time_series.iloc[0] - 1) * 100,
'volatility': time_series.pct_change().std() * 100
}

return results

def generate_insights(self, results):
"""生成洞察"""
insights = []

if results['distribution']['skewness'] > 1:
insights.append("数据呈现右偏分布,存在高值异常点")
elif results['distribution']['skewness'] < -1:
insights.append("数据呈现左偏分布,存在低值异常点")

if 'trend' in results:
if results['trend']['growth_rate'] > 10:
insights.append(f"目标指标呈现强劲增长趋势 (+{results['trend']['growth_rate']:.1f}%)")
elif results['trend']['growth_rate'] < -10:
insights.append(f"目标指标呈现下降趋势 ({results['trend']['growth_rate']:.1f}%)")

return insights

# 使用分析模板
template = DataAnalysisTemplate(cleaned_data, 'total_amount', 'order_date')
quick_results = template.quick_analysis()
insights = template.generate_insights(quick_results)

print("快速分析结果:")
print(f"基础统计: {quick_results['basic_stats']}")
print(f"分布特征: {quick_results['distribution']}")
if 'trend' in quick_results:
print(f"趋势分析: {quick_results['trend']}")
print(f"\n洞察:")
for insight in insights:
print(f"• {insight}")

🔮 总结与展望

通过这个完整的Python数据分析项目,我们学习了:

核心技能

  1. 数据处理: 使用Pandas进行数据清洗和转换
  2. 统计分析: 描述性统计、相关性分析、假设检验
  3. 可视化: Matplotlib、Seaborn、Plotly多种可视化工具
  4. 机器学习: 预测建模和客户细分
  5. 报告生成: 自动化分析报告和洞察提取

最佳实践

  • 模块化设计: 将分析流程封装成可重用的类和函数
  • 数据质量: 始终关注数据质量和完整性
  • 可视化原则: 选择合适的图表类型,注重可读性
  • 性能优化: 处理大数据时的内存和计算优化
  • 业务导向: 分析结果要能指导业务决策

进阶方向

  • 深度学习: 使用TensorFlow/PyTorch进行高级建模
  • 实时分析: 流数据处理和实时仪表板
  • A/B测试: 实验设计和因果推断
  • 自然语言处理: 文本数据分析和情感分析
  • 时间序列: 高级时间序列分析和预测

数据分析是一个不断学习和实践的过程。掌握了这些基础技能后,你就可以应对大部分的数据分析挑战,并为业务决策提供有价值的洞察。


你在数据分析实践中遇到过哪些有趣的问题?欢迎在评论区分享你的经验和发现!