pandas实战1:淘宝用户行为分析

数据概览

py 复制代码
# 数据概览
print("\n数据概览:")
print(f"时间范围:{df['time'].min()} 至 {df['time'].max()}")
print(f"用户数:{df['user_id'].nunique()}")
print(f"行为类型分布:\n{df['behavior_type'].value_counts()}")

.nunique() 全称为 "number of unique "(唯一值数量),用于快速计算某列中不同值的个数

典型应用场景:

  • 计算独立用户数(UV)
  • 统计不同商品/类目的数量
  • 分析唯一访问次数等

相关方法对比:

方法 描述 示例
.nunique() 返回唯一值数量 user_id.nunique() → 1000(个独立用户)
.unique() 返回唯一值数组 user_id.unique() → array([1, 2, 3, ...])
.value_counts() 返回各值出现次数 user_id.value_counts() → 用户1: 50次,用户2: 30次...
  1. 计算关键指标
py 复制代码
# 独立用户数(UV)
uv = df['user_id'].nunique() 

# 独立商品数
items_count = df['item_id'].nunique()

# 日均UV
daily_uv = df.groupby('date')['user_id'].nunique()
  1. 分析用户行为质量
py 复制代码
# 计算人均行为次数
total_actions = len(df) # 总次数
unique_users = df['user_id'].nunique() # 人数
avg_actions = total_actions / unique_users # 人均
  1. 结合分组分析
py 复制代码
# 各行为类型的独立用户数
behavior_uv = df.groupby('behavior_type')['user_id'].nunique()

# 每小时独立用户数
hourly_uv = df.groupby('hour')['user_id'].nunique()
  1. 漏斗分析
py 复制代码
funnel = {
    '曝光': df[df['behavior_type']=='pv']['user_id'].nunique(),
    '加购': df[df['behavior_type']=='cart']['user_id'].nunique(),
    '购买': df[df['behavior_type']=='buy']['user_id'].nunique()
}
  1. 用户留存分析
py 复制代码
# 计算次日留存
day1_users = df[df['date']=='2023-01-01']['user_id'].unique()
day2_users = df[df['date']=='2023-01-02']['user_id'].unique()
retention = len(set(day1_users) & set(day2_users)) / len(day1_users)

Q:为什么 nunique() 结果比预期少?
A:可能原因:

  • 数据中存在空值(NaN不会被计数,除非用 dropna=False
  • 用户ID存在重复或错误(如测试账号)
py 复制代码
# 包含空值的计数
uv_with_nan = df['user_id'].nunique(dropna=False)

# 检查数据质量
print(df['user_id'].isna().sum()) # 空值数量
print(df['user_id'].value_counts().head()) # 高频ID

数据清洗

py 复制代码
# 数据清洗
df.dropna(inplace=True) # 处理缺失数据
df.drop_duplicates(subset=['user_id','item_id','time'], keep='first', inplace=True) # 去重
df['datetime'] = pd.to_datetime(df['time']) # 时间格式转换
df['date'] = pd.to_datetime(df['time']).dt.date # 从时间戳提取日期 

pd.to_datetime() 是 Pandas 中将输入转换为标准时间格式的函数

参数 示例 用途 产品分析场景
format format='%m/%d/%Y' 指定输入格式 处理美国格式日期
unit unit='ms' 时间戳单位 处理JS生成的毫秒时间戳
errors errors='coerce' 错误处理 自动过滤无效日期
dayfirst dayfirst=True 日在前格式 处理欧洲日期如15/07/2024
  1. 原始数据清洗
python 复制代码
# 电商订单时间处理(多种原始格式)
df['order_time'] = pd.to_datetime(df['raw_time'], format='%Y/%m/%d %H:%M:%S')
  1. 行为分析时间提取
python 复制代码
# 从时间戳提取关键维度
df['date'] = pd.to_datetime(df['timestamp']).dt.date  # 日期
df['hour'] = pd.to_datetime(df['timestamp']).dt.hour  # 小时
  1. 处理混合格式
python 复制代码
# 自动推断多种格式(如"2024-07-15"和"15/07/24")
df['time'] = pd.to_datetime(df['raw_time'], infer_datetime_format=True)
  1. 电商大促分析
python 复制代码
# 计算用户响应时间(从浏览到购买)
df['view_time'] = pd.to_datetime(df['view_timestamp'])
df['buy_time'] = pd.to_datetime(df['buy_timestamp'])
df['response_time'] = (df['buy_time'] - df['view_time']).dt.total_seconds()
  1. 用户活跃时段分析
python 复制代码
# 原始数据:'time'列为字符串或时间戳
df['datetime'] = pd.to_datetime(df['time'])
df['hour'] = df['datetime'].dt.hour

# 24小时活跃分布
hourly_uv = df.groupby('hour')['user_id'].nunique()
hourly_uv.plot(kind='bar', title='用户活跃时段分布')
  1. 关键业务时间字段校验
python 复制代码
# 检查是否有未来时间或极旧时间
dates = pd.to_datetime(df['order_time'])
invalid_dates = dates[(dates > pd.Timestamp.now()) | (dates < pd.Timestamp('2000-01-01'))]

Q:报错OutOfBoundsDatetime
A:可能原因:时间超出Timestamp范围

python 复制代码
pd.to_datetime(df['time'], errors='coerce')  # 将超界值转为NaT

定义行为类型编码规则

python 复制代码
# 定义行为类型编码规则
behavior_map = {
    1: '曝光', 2: '加购', 3: '收藏', 4: '购买',
    '1': '曝光', '2': '加购', '3': '收藏', '4': '购买',
    'pv': '曝光', 'cart': '加购', 'fav': '收藏', 'buy': '购买'
}
# 统一转换(兼容数字/英文编码)
df['behavior'] = df['behavior_type'].map(behavior_map)

.map() 是一个Series 对象的方法 ,用于根据给定的映射关系替换 Series 中的每个值。

例如:将原始的行为类型编码(数字或英文)统一转换为中文描述。

  1. 映射转换
    Series 中的每个元素按照指定的映射关系进行转换
python 复制代码
# 示例:将1→'曝光',2→'加购'...
df['behavior'] = df['behavior_type'].map(behavior_map)
  1. 使用函数映射
python 复制代码
# 将购买金额分段
df['price_level'] = df['price'].map(lambda x: '高价' if x > 100 else '低价')
  1. 通过另一个Series映射
python 复制代码
# 从其他表获取映射关系
id_to_name = pd.Series(['曝光','加购'], index=[1,2])
df['behavior'] = df['behavior_type'].map(id_to_name)
  1. 处理未知值
python 复制代码
# 未知编码转为'其他'
df['behavior'] = df['behavior_type'].map(behavior_map).fillna('其他')

Q:映射后出现 NaN
A:原因:原始值不在映射字典中

python 复制代码
# 方法1:填充默认值
df['behavior'] = df['behavior_type'].map(behavior_map).fillna('未知行为')

# 方法2:检查缺失值
missing = df[df['behavior'].isna()]['behavior_type'].unique()
print("未映射的值:", missing)

Q:映射速度慢

python 复制代码
# 对大数据集更高效的方法
df['behavior'] = df['behavior_type'].replace(behavior_map)

建议:

  1. 映射表统一管理
    behavior_map 保存在单独配置文件中,方便多份代码复用:
python 复制代码
# config.py
BEHAVIOR_MAP = {
    1: '曝光', 
    2: '加购',
    ... 
}

# analysis.py
from config import BEHAVIOR_MAP
df['behavior'] = df['behavior_type'].map(BEHAVIOR_MAP)
  1. 验证映射完整性
python 复制代码
# 检查原始值是否全部被覆盖
unmapped = set(df['behavior_type'].unique()) - set(behavior_map.keys())
assert len(unmapped) == 0, f"未映射的值:{unmapped}"

基础指标计算

python 复制代码
# 基础指标计算
daily_data = df.groupby('date').agg(
    uv=('user_id', 'nunique'),  # 对user_id去重计数 → UV  (对user_id进行nunique)
    pv=('user_id', 'count')     # 对user_id直接计数 → PV  (对user_id进行count)
)

.agg()aggregate (聚合)的缩写,用于对分组后的数据执行多种聚合计算

.agg() 可以对数据:

  • 同时计算多个指标(如UV、PV)
  • 对不同列应用不同计算(如对用户ID去重计数,对访问次数直接计数)
  • 自定义聚合逻辑(支持内置函数或自定义函数)
  1. 多列不同计算
python 复制代码
df.groupby('date').agg(
    uv=('user_id', 'nunique'),
    avg_price=('price', 'mean'),  # 计算均价
    max_time=('timestamp', 'max')  # 最晚访问时间
)
  1. 同列多指标
python 复制代码
df.groupby('category').agg(
    price_stats=('price', ['min', 'max', 'median']),
    user_variety=('user_id', 'nunique')
)
  1. 自定义函数
python 复制代码
# 计算购买转化率(购买用户/活跃用户)
def conversion_rate(group):
    return (group['behavior'] == '购买').sum() / len(group)

df.groupby('date').apply(conversion_rate)
  1. 电商场景核心指标
python 复制代码
daily_kpis = df.groupby('date').agg(
    uv=('user_id', 'nunique'),
    pv=('pageview_id', 'count'),
    gmv=('order_amount', 'sum'),
    conversion=('is_purchase', 'mean')  # 转化率
).reset_index()
  1. 用户分群分析
python 复制代码
user_segments = df.groupby('user_id').agg(
    first_date=('date', 'min'),
    last_date=('date', 'max'),
    purchase_count=('order_id', 'nunique'),
    avg_spend=('amount', 'mean')
)

Q:列名冲突
A:原因:多个聚合使用相同列名

python 复制代码
df.groupby('date')['user_id'].agg(
    UV='nunique',
    PV='count'
)

Q:空值影响

python 复制代码
df.groupby('date').agg(
    uv=('user_id', lambda x: x.notna().nunique())
)

用户转化漏斗分析

python 复制代码
# 用户转化漏斗分析
fig = px.funnel(funnel_data.reset_index(), # 数据(需包含行为阶段和用户数)
               x='user_id', # 各阶段的用户量(决定漏斗宽度)
               y='behavior', # 行为阶段(决定漏斗高度方向)
               title='用户行为漏斗分析') 
fig.write_html("C:\Temp\funnel.html") # 保存HTML文件
参数 作用 您的数据示例
x 各阶段的量级 曝光:8170用户 → 购买:3869用户
y 行为阶段顺序 曝光 → 加购 → 收藏 → 购买

funnel (漏斗)是一种专门用于展示多阶段转化过程 的图表类型。.funnel()Plotly Express 库中用于创建漏斗图的函数。

  1. 多维度对比
python 复制代码
# 对比不同用户群的漏斗
px.funnel(df, x='user_id', y='behavior', color='user_type')

Q:漏斗阶段倒置
A:原因:行为阶段未正确排序

python 复制代码
funnel_data = funnel_data.sort_values('user_id', ascending=False)

Q:数据不匹配
A:原因:确保x为数值列,y为分类列

python 复制代码
print(funnel_data.dtypes)  
# 应显示: user_id:int, behavior:object

建议:

  1. 用渐变色表示转化方向
python 复制代码
import plotly.express as px

# 基础渐变色(按阶段顺序):用户量大的阶段颜色深,量小的颜色浅
fig = px.funnel(
    funnel_data.reset_index(),
    x='user_id',
    y='behavior',
    color='user_id', # 关键:用用户数作为颜色依据
    color_continuous_scale='Blues', # 使用蓝色渐变
    title='用户行为漏斗(按量级渐变)'
)
fig.show()

# 自定义阶段颜色映射:每个阶段固定颜色,绿色→红色表示转化路径;适合强调关键流失点
stage_colors = { # 定义颜色梯度(从绿到红表示转化率下降)
    '曝光': '#2ECC71',  # 绿色
    '加购': '#F1C40F',  # 黄色
    '收藏': '#E67E22',  # 橙色
    '购买': '#E74C3C'   # 红色
}
fig = px.funnel(
    funnel_data.reset_index(),
    x='user_id',
    y='behavior',
    color='behavior', # 按行为类型着色
    color_discrete_map=stage_colors # 自定义颜色映射
)
fig.update_layout(showlegend=True)

# 动态计算颜色(基于转换率):红色(低转化率)→ 绿色(高转化率);直观显示各阶段效率
funnel_data['conversion_rate'] = funnel_data['user_id'] / funnel_data['user_id'].iloc[0] # 计算各阶段相对于曝光的转化率
fig = px.funnel(
    funnel_data.reset_index(),
    x='user_id',
    y='behavior',
    color='conversion_rate', # 用转化率作为颜色依据
    color_continuous_scale=['red', 'yellow', 'green'], # 自定义渐变
    range_color=[0, 1], # 颜色范围0%~100%
    title='用户行为漏斗(按转化率渐变)'
)
fig.update_coloraxes(colorbar_title='转化率')
  1. 3D漏斗效果
python 复制代码
fig.update_traces(
    marker=dict(line=dict(width=1, color='gray')),
    opacity=0.8  # 增加透明度增强层次感
)
  1. 交互增强
python 复制代码
fig.update_layout(hovermode="x unified")  # 悬停显示详细信息

转化率分析

python 复制代码
# 转化率分析
if '曝光' in funnel_data.index and '购买' in funnel_data.index: # 检查数据中是否存在"曝光"和"购买"两个关键节点
    conversion_rate = funnel_data['购买'] / funnel_data['曝光'] # 转化率=购买人数 ÷ 曝光人数
    print(f"\n曝光→购买转化率:{conversion_rate:.2%}")

完整代码

py 复制代码
import pandas as pd
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import plotly.express as px

# 显示设置
pd.options.display.max_columns=999 # 随便设置一个大的数字,可以让隐藏的信息都显示出来
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 微软雅黑
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示为方块的问题

# 数据示例
df = pd.read_csv('C:\Temp\淘宝用户行为.csv')
print(df.head())  # 查看前5行

# 数据概览
print("\n数据概览:")
print(f"时间范围:{df['time'].min()} 至 {df['time'].max()}")
print(f"用户数:{df['user_id'].nunique()}")
print(f"行为类型分布:\n{df['behavior_type'].value_counts()}")

# 数据清洗
df.dropna(inplace=True) # 处理缺失数据
df.drop_duplicates(subset=['user_id','item_id','time'], keep='first', inplace=True) # 去重
df['datetime'] = pd.to_datetime(df['time'])
df['date'] = pd.to_datetime(df['time']).dt.date # 时间格式转换

# 定义行为类型编码规则
behavior_map = {
    1: '曝光', 2: '加购', 3: '收藏', 4: '购买',
    '1': '曝光', '2': '加购', '3': '收藏', '4': '购买',
    'pv': '曝光', 'cart': '加购', 'fav': '收藏', 'buy': '购买'
}
# 统一转换(兼容数字/英文编码)
df['behavior'] = df['behavior_type'].map(behavior_map)

# 基础指标计算
daily_data = df.groupby('date').agg(
    uv=('user_id', 'nunique'),  # 去重用户数
    pv=('user_id', 'count')     # 总访问量
)

# 行为分布统计(两种方式对比)
print("\n行为记录数(总次数):")
print(df['behavior'].value_counts())

print("\n独立用户数(去重):")
funnel_data = df.groupby('behavior')['user_id'].nunique().sort_values(ascending=False) # 计算各行为用户数
print(funnel_data)

# 可视化
daily_data.plot(title='日活跃用户趋势', figsize=(10,5)) # 绘制UV/PV趋势图
plt.xlabel('日期')
plt.ylabel('数量')
plt.savefig('C:\Temp\uv_pv.png') # 保存图片

# 用户转化漏斗分析
fig = px.funnel(funnel_data.reset_index(),
               x='user_id',
               y='behavior',
               title='用户行为漏斗分析') # 绘制漏斗图
fig.write_html("C:\Temp\funnel.html") # 保存HTML文件

# 用户分群
user_rfm = df[df['behavior']=='购买'].groupby('user_id').agg( # 计算每个用户的最近购买日、购买频次
    last_date=('date', 'max'),
    frequency=('item_id', 'count')
)
user_rfm['high_value'] = user_rfm['frequency'] > user_rfm['frequency'].quantile(0.8) # 标记高价值用户(前20%)
user_rfm.to_csv('C:\Temp\用户价值分层.csv', encoding='utf-8-sig')  # 保存为CSV文件

# 用户活跃时段分析
df['hour'] = pd.to_datetime(df['time']).dt.hour # 提取小时
hourly_activity = df.groupby('hour')['user_id'].nunique() # 按小时统计独立用户数
hourly_activity.plot(kind='bar', title='用户活跃时段分布')
plt.xlabel('小时')
plt.ylabel('独立用户数')
plt.savefig('C:\Temp\用户活跃时段分布.png') # 保存图片

# 转化率分析
if '曝光' in funnel_data.index and '购买' in funnel_data.index:
    conversion_rate = funnel_data['购买'] / funnel_data['曝光']
    print(f"\n曝光→购买转化率:{conversion_rate:.2%}")

数据来源:淘宝用户行为_数据集-阿里云天池

相关推荐
AI视觉网奇4 分钟前
音频获取长度
java·前端·python
寄思~23 分钟前
学习笔记:封装和单继承
开发语言·笔记·python·学习
E_ICEBLUE43 分钟前
Python 操作 Word 文档:主流库对比与选择指南
开发语言·经验分享·python·word·办公自动化
倔强青铜三44 分钟前
苦练Python第38天:input() 高级处理,安全与异常管理
人工智能·python·面试
大模型真好玩1 小时前
深入浅出LangChain AI Agent智能体开发教程(六)—两行代码LangChain Agent API快速搭建智能体
人工智能·python·agent
德育处主任Pro1 小时前
『React』 组件通信全攻略
python·opencv·matplotlib
七七软件开发2 小时前
一对一交友小程序 / APP 系统架构分析
java·python·小程序·系统架构·php
电商数据girl2 小时前
如何利用API接口与网页爬虫协同进行电商平台商品数据采集?
大数据·开发语言·人工智能·python·django·json
万粉变现经纪人2 小时前
如何解决pip安装报错ModuleNotFoundError: No module named ‘dash’问题
python·scrapy·pycharm·flask·pip·策略模式·dash
Monkey的自我迭代2 小时前
逻辑回归参数调优实战指南
python·机器学习·逻辑回归·数据处理·下采样·过采样