第12章 综合实战案例
12.1 电商用户行为数据分析实战
电商用户行为分析是数据分析的经典应用场景,通过分析用户的点击、加购、购买等行为,可以帮助企业优化产品推荐、提升转化率。本节我们将使用一个模拟的电商用户行为数据集来进行完整的分析流程。
核心分析方法表格
| 功能名称 | 实例调用方法 | 具体功能与注意事项 |
|---|---|---|
| 数据加载 | pd.read_csv('user_behavior.csv') | 加载CSV格式的用户行为数据,注意编码格式和分隔符 |
| 行为类型统计 | df['behavior_type'].value_counts() | 统计不同行为类型的频次,了解用户主要行为分布 |
| 转化漏斗分析 | 自定义函数计算各行为到购买的转化率 | 需要按用户ID分组,计算从浏览到购买的完整路径 |
| 用户活跃度分析 | df.groupby('user_id').size() | 统计每个用户的总行为次数,识别高价值用户 |
让我们来看一个完整的电商用户行为分析示例:
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体支持(避免中文显示乱码)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建模拟的电商用户行为数据
# 在实际项目中,这里会从真实数据文件读取
np.random.seed(42)
n_records = 10000
# 生成模拟数据
user_ids = np.random.randint(1, 1001, n_records) # 1000个用户
item_ids = np.random.randint(1, 501, n_records) # 500个商品
categories = np.random.randint(1, 51, n_records) # 50个商品类别
behaviors = np.random.choice(['pv', 'cart', 'fav', 'buy'],
size=n_records,
p=[0.7, 0.15, 0.1, 0.05]) # 行为类型及概率
timestamps = pd.date_range('2023-01-01', periods=n_records, freq='1min')
# 创建DataFrame
df = pd.DataFrame({
'user_id': user_ids,
'item_id': item_ids,
'category_id': categories,
'behavior_type': behaviors,
'timestamp': timestamps
})
# 查看数据基本信息
print("数据形状:", df.shape)
print("\n数据前5行:")
print(df.head())
# 检查缺失值
print("\n缺失值统计:")
print(df.isnull().sum())
# 行为类型分布分析
behavior_counts = df['behavior_type'].value_counts()
print("\n行为类型分布:")
print(behavior_counts)
# 可视化行为类型分布
plt.figure(figsize=(10, 6))
sns.barplot(x=behavior_counts.index, y=behavior_counts.values)
plt.title('用户行为类型分布')
plt.xlabel('行为类型')
plt.ylabel('频次')
plt.show()
# 计算转化率(以pv为起点)
total_pv = behavior_counts.get('pv', 0)
total_buy = behavior_counts.get('buy', 0)
conversion_rate = (total_buy / total_pv) * 100 if total_pv > 0 else 0
print(f"\n整体转化率: {conversion_rate:.2f}%")
# 用户活跃度分析
user_activity = df.groupby('user_id').size().reset_index(name='activity_count')
print("\n用户活跃度统计:")
print(user_activity.describe())
# 识别高价值用户(行为次数前10%)
top_users_threshold = user_activity['activity_count'].quantile(0.9)
high_value_users = user_activity[user_activity['activity_count'] >= top_users_threshold]
print(f"\n高价值用户数量: {len(high_value_users)}")
print(f"占总用户比例: {len(high_value_users)/len(user_activity)*100:.2f}%")这个示例展示了电商用户行为分析的基本流程:从数据加载、基础统计、行为分布可视化到用户价值识别。在实际项目中,你可能还需要进行更深入的分析,比如用户留存分析、商品关联规则挖掘等。
电商用户行为分析的核心价值在于理解用户的行为模式和转化路径,从而优化产品设计和营销策略。通过这样的分析,企业可以精准定位高价值用户群体,提升整体业务表现。
12.2 股票价格时间序列分析
股票价格分析是时间序列分析的重要应用领域。通过对历史股价数据的分析,我们可以识别趋势、周期性和潜在的交易信号。本节将演示如何使用Python进行基础的股票价格时间序列分析。
核心分析方法表格
| 功能名称 | 实例调用方法 | 具体功能与注意事项 |
|---|---|---|
| 获取股票数据 | yfinance.download('AAPL', start='2023-01-01') | 需要安装yfinance库,注意网络连接和API限制 |
| 移动平均线 | df['Close'].rolling(window=20).mean() | 常用的技术指标,window参数决定平滑程度 |
| 收益率计算 | df['Close'].pct_change() | 计算日收益率,用于风险和回报分析 |
| 波动率分析 | returns.rolling(window=20).std() | 衡量价格波动程度,重要的风险指标 |
由于我们无法实时获取真实的股票数据,下面使用模拟数据来演示分析流程:
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建模拟股票价格数据
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2023-12-31', freq='D')
# 模拟随机游走过程
returns = np.random.normal(0.001, 0.02, len(dates)) # 日均收益0.1%,波动率2%
price = 100 * np.exp(np.cumsum(returns)) # 从100开始的价格
# 创建DataFrame
stock_data = pd.DataFrame({
'Date': dates,
'Close': price
})
stock_data.set_index('Date', inplace=True)
# 计算技术指标
# 20日移动平均线
stock_data['MA20'] = stock_data['Close'].rolling(window=20).mean()
# 50日移动平均线
stock_data['MA50'] = stock_data['Close'].rolling(window=50).mean()
# 日收益率
stock_data['Returns'] = stock_data['Close'].pct_change()
# 20日波动率
stock_data['Volatility'] = stock_data['Returns'].rolling(window=20).std()
# 基础价格走势图
plt.figure(figsize=(12, 8))
# 子图1: 价格和移动平均线
plt.subplot(2, 1, 1)
plt.plot(stock_data.index, stock_data['Close'], label='收盘价', alpha=0.7)
plt.plot(stock_data.index, stock_data['MA20'], label='20日均线', linewidth=2)
plt.plot(stock_data.index, stock_data['MA50'], label='50日均线', linewidth=2)
plt.title('股票价格与移动平均线')
plt.legend()
plt.grid(True, alpha=0.3)
# 子图2: 波动率
plt.subplot(2, 1, 2)
plt.plot(stock_data.index, stock_data['Volatility'], color='red', alpha=0.7)
plt.title('20日波动率')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 收益率分布分析
plt.figure(figsize=(10, 6))
sns.histplot(stock_data['Returns'].dropna(), kde=True, bins=50)
plt.title('日收益率分布')
plt.xlabel('收益率')
plt.ylabel('频次')
plt.grid(True, alpha=0.3)
plt.show()
# 基础统计信息
print("股票价格统计信息:")
print(f"起始价格: {stock_data['Close'].iloc[0]:.2f}")
print(f"结束价格: {stock_data['Close'].iloc[-1]:.2f}")
print(f"最高价格: {stock_data['Close'].max():.2f}")
print(f"最低价格: {stock_data['Close'].min():.2f}")
print(f"年化收益率: {(stock_data['Close'].iloc[-1]/stock_data['Close'].iloc[0] - 1) * 100:.2f}%")
print("\n收益率统计:")
print(f"平均日收益率: {stock_data['Returns'].mean()*100:.4f}%")
print(f"日收益率标准差: {stock_data['Returns'].std()*100:.4f}%")
print(f"年化波动率: {stock_data['Returns'].std()*np.sqrt(252)*100:.2f}%")股票价格时间序列分析帮助投资者理解市场动态和风险特征。移动平均线可以识别趋势方向,波动率指标则衡量市场风险。虽然历史数据不能保证未来表现,但这些分析工具为投资决策提供了重要的参考依据。
12.3 社交媒体情感倾向探索
社交媒体情感分析是自然语言处理的重要应用,通过分析用户在社交媒体上发布的文本内容,可以了解公众对特定话题、产品或事件的情感倾向。本节将演示如何进行基础的情感分析。
核心分析方法表格
| 功能名称 | 实例调用方法 | 具体功能与注意事项 |
|---|---|---|
| 文本情感评分 | TextBlob(text).sentiment.polarity | 返回-1到1的情感极性分数,需要安装textblob库 |
| 情感分类 | 自定义阈值判断正面/负面情感 | 通常以0为界,>0为正面,<0为负面 |
| 情感趋势分析 | 按时间分组计算平均情感得分 | 需要时间戳字段,用于观察情感变化 |
| 关键词提取 | CountVectorizer 或正则表达式 | 识别影响情感的关键词汇 |
下面使用模拟的社交媒体评论数据进行情感分析演示:
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from textblob import TextBlob
from datetime import datetime, timedelta
import re
# 设置中文字体支持(注意:TextBlob对中文支持有限,这里主要演示英文)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建模拟社交媒体评论数据
np.random.seed(42)
n_comments = 1000
# 生成模拟评论文本(英文)
positive_words = ['great', 'amazing', 'excellent', 'love', 'wonderful', 'fantastic']
negative_words = ['terrible', 'awful', 'hate', 'disappointing', 'bad', 'worst']
neutral_words = ['okay', 'fine', 'normal', 'average', 'standard']
comments = []
sentiments_actual = []
timestamps = []
start_date = datetime(2023, 1, 1)
for i in range(n_comments):
# 随机选择情感倾向
sentiment_type = np.random.choice(['positive', 'negative', 'neutral'], p=[0.4, 0.3, 0.3])
# 生成对应情感的评论
if sentiment_type == 'positive':
comment = f"This product is {np.random.choice(positive_words)}! I really {np.random.choice(['love', 'like'])} it."
actual_sent = 1
elif sentiment_type == 'negative':
comment = f"This product is {np.random.choice(negative_words)}. I {np.random.choice(['hate', 'dislike'])} it."
actual_sent = -1
else:
comment = f"This product is {np.random.choice(neutral_words)}. It's okay."
actual_sent = 0
comments.append(comment)
sentiments_actual.append(actual_sent)
timestamps.append(start_date + timedelta(days=i//10)) # 每10条评论一天
# 创建DataFrame
social_data = pd.DataFrame({
'comment': comments,
'actual_sentiment': sentiments_actual,
'timestamp': timestamps
})
# 使用TextBlob进行情感分析
def get_sentiment_polarity(text):
"""获取文本的情感极性分数"""
try:
blob = TextBlob(text)
return blob.sentiment.polarity
except:
return 0
# 应用情感分析函数
social_data['sentiment_score'] = social_data['comment'].apply(get_sentiment_polarity)
# 将情感分数转换为分类
def classify_sentiment(score):
"""根据分数分类情感"""
if score > 0.1:
return 'positive'
elif score < -0.1:
return 'negative'
else:
return 'neutral'
social_data['predicted_sentiment'] = social_data['sentiment_score'].apply(classify_sentiment)
# 情感分布统计
sentiment_counts = social_data['predicted_sentiment'].value_counts()
print("情感分布统计:")
print(sentiment_counts)
# 可视化情感分布
plt.figure(figsize=(10, 6))
colors = {'positive': 'green', 'neutral': 'gray', 'negative': 'red'}
sentiment_counts.plot(kind='bar', color=[colors.get(x, 'blue') for x in sentiment_counts.index])
plt.title('社交媒体情感分布')
plt.xlabel('情感类别')
plt.ylabel('评论数量')
plt.xticks(rotation=0)
plt.grid(True, alpha=0.3)
plt.show()
# 情感趋势分析(按周)
social_data['week'] = social_data['timestamp'].dt.to_period('W')
weekly_sentiment = social_data.groupby('week')['sentiment_score'].mean()
plt.figure(figsize=(12, 6))
plt.plot(weekly_sentiment.index.astype(str), weekly_sentiment.values, marker='o')
plt.title('每周平均情感趋势')
plt.xlabel('周')
plt.ylabel('平均情感分数')
plt.xticks(rotation=45)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 情感分析准确率(与模拟的真实标签比较)
# 注意:在真实场景中不会有真实标签,这里仅用于演示
accuracy = (social_data['predicted_sentiment'] ==
social_data['actual_sentiment'].map({1: 'positive', -1: 'negative', 0: 'neutral'})).mean()
print(f"\n情感分析准确率: {accuracy*100:.2f}%")
# 显示一些示例评论和情感分数
print("\n示例评论情感分析:")
for i in [0, 100, 200, 300]:
print(f"评论: {social_data['comment'].iloc[i]}")
print(f"情感分数: {social_data['sentiment_score'].iloc[i]:.3f}")
print(f"预测情感: {social_data['predicted_sentiment'].iloc[i]}")
print("-" * 50)社交媒体情感分析为企业提供了宝贵的用户反馈洞察。通过监控公众情感倾向,企业可以及时调整产品策略、回应用户关切,并在危机发生前采取预防措施。需要注意的是,情感分析的准确性受到语言复杂性、讽刺语境等因素的影响,因此结果应结合人工审核使用。
12.4 公共数据集(如 Titanic、鸢尾花)完整分析流程
公共数据集是学习数据分析的理想材料,其中泰坦尼克号(Titanic)生存预测和鸢尾花(Iris)分类是最经典的入门数据集。本节将以泰坦尼克号数据集为例,展示完整的数据分析流程。
核心分析方法表格
| 功能名称 | 实例调用方法 | 具体功能与注意事项 |
|---|---|---|
| 加载内置数据集 | sns.load_dataset('titanic') | Seaborn提供多个经典数据集,无需额外下载 |
| 生存率分析 | df.groupby('sex')['survived'].mean() | 按不同特征分组计算生存率 |
| 相关性分析 | df.corr() | 分析数值特征间的相关性,注意只包含数值列 |
| 可视化生存分布 | sns.countplot(data=df, x='class', hue='survived') | 比较不同类别下的生存情况 |
让我们使用Seaborn内置的泰坦尼克号数据集进行完整分析:
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 加载泰坦尼克号数据集
try:
titanic = sns.load_dataset('titanic')
print("成功加载泰坦尼克号数据集")
except:
# 如果无法加载,创建模拟数据
print("无法加载内置数据集,创建模拟数据")
np.random.seed(42)
n_passengers = 891
# 模拟关键特征
survived = np.random.choice([0, 1], size=n_passengers, p=[0.62, 0.38]) # 约38%生存率
pclass = np.random.choice([1, 2, 3], size=n_passengers, p=[0.24, 0.21, 0.55])
sex = np.random.choice(['male', 'female'], size=n_passengers, p=[0.65, 0.35])
age = np.random.normal(30, 14, n_passengers)
age = np.clip(age, 0.42, 80) # 年龄范围限制
sibsp = np.random.poisson(0.5, n_passengers)
parch = np.random.poisson(0.4, n_passengers)
fare = np.random.exponential(32, n_passengers) # 平均票价约32
embarked = np.random.choice(['C', 'Q', 'S'], size=n_passengers, p=[0.19, 0.09, 0.72])
titanic = pd.DataFrame({
'survived': survived,
'pclass': pclass,
'sex': sex,
'age': age,
'sibsp': sibsp,
'parch': parch,
'fare': fare,
'embarked': embarked
})
# 查看数据基本信息
print("数据集形状:", titanic.shape)
print("\n数据类型:")
print(titanic.dtypes)
print("\n前5行数据:")
print(titanic.head())
print("\n缺失值统计:")
print(titanic.isnull().sum())
# 整体生存率
overall_survival_rate = titanic['survived'].mean()
print(f"\n整体生存率: {overall_survival_rate*100:.2f}%")
# 按性别分析生存率
survival_by_sex = titanic.groupby('sex')['survived'].mean()
print("\n按性别分组的生存率:")
print(survival_by_sex)
# 按船舱等级分析生存率
survival_by_class = titanic.groupby('pclass')['survived'].mean()
print("\n按船舱等级分组的生存率:")
print(survival_by_class)
# 创建综合可视化
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# 图1: 性别与生存
sns.countplot(data=titanic, x='sex', hue='survived', ax=axes[0,0])
axes[0,0].set_title('性别与生存情况')
axes[0,0].set_xlabel('性别')
axes[0,0].set_ylabel('人数')
# 图2: 船舱等级与生存
sns.countplot(data=titanic, x='pclass', hue='survived', ax=axes[0,1])
axes[0,1].set_title('船舱等级与生存情况')
axes[0,1].set_xlabel('船舱等级')
axes[0,1].set_ylabel('人数')
# 图3: 年龄分布与生存
titanic.boxplot(column='age', by='survived', ax=axes[1,0])
axes[1,0].set_title('年龄与生存情况')
axes[1,0].set_xlabel('生存状态 (0=死亡, 1=生存)')
axes[1,0].set_ylabel('年龄')
# 图4: 票价与生存
titanic.boxplot(column='fare', by='survived', ax=axes[1,1])
axes[1,1].set_title('票价与生存情况')
axes[1,1].set_xlabel('生存状态 (0=死亡, 1=生存)')
axes[1,1].set_ylabel('票价')
plt.tight_layout()
plt.show()
# 相关性热力图(仅数值特征)
numeric_features = titanic.select_dtypes(include=[np.number])
correlation_matrix = numeric_features.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('特征相关性热力图')
plt.show()
# 多因素交叉分析:性别+船舱等级
survival_cross = titanic.groupby(['sex', 'pclass'])['survived'].mean().unstack()
print("\n性别与船舱等级交叉的生存率:")
print(survival_cross)
# 可视化交叉分析
plt.figure(figsize=(10, 6))
survival_cross.plot(kind='bar', stacked=False)
plt.title('性别与船舱等级对生存率的影响')
plt.xlabel('性别')
plt.ylabel('生存率')
plt.legend(title='船舱等级')
plt.xticks(rotation=0)
plt.grid(True, alpha=0.3)
plt.show()
# 年龄分组分析
titanic['age_group'] = pd.cut(titanic['age'],
bins=[0, 12, 18, 35, 60, 100],
labels=['儿童', '青少年', '青年', '中年', '老年'])
survival_by_age = titanic.groupby('age_group')['survived'].mean()
print("\n按年龄组分组的生存率:")
print(survival_by_age)
# 家庭规模分析(sibsp + parch + 1)
titanic['family_size'] = titanic['sibsp'] + titanic['parch'] + 1
survival_by_family = titanic.groupby('family_size')['survived'].mean()
plt.figure(figsize=(10, 6))
plt.plot(survival_by_family.index, survival_by_family.values, marker='o')
plt.title('家庭规模与生存率的关系')
plt.xlabel('家庭规模')
plt.ylabel('生存率')
plt.grid(True, alpha=0.3)
plt.show()泰坦尼克号数据分析展示了从数据探索、清洗、可视化到深入洞察的完整流程。通过多维度的分析,我们发现性别、船舱等级、年龄等因素都显著影响生存概率。这种系统性的分析方法可以应用于各种实际业务场景,帮助我们从数据中提取有价值的见解。
公共数据集的价值在于提供了标准化的练习材料,让学习者能够专注于分析方法本身,而不必担心数据获取和预处理的复杂性。掌握这些经典数据集的分析技巧,为处理真实世界的复杂数据奠定了坚实基础。