一、数据加载:先把数据读进来

1.1 导入必备库

import pandas as pd    # 数据处理神器,没有它啥也干不了
import numpy as np     # 数值计算库,pandas底层靠它

1.2 读取行为数据(大文件分块读取)

原始数据有1300多万行,直接读可能内存撑不住,所以用分块读取的方式:

# chunksize=10000 表示每次只读1万行,分批加载
data = pd.read_csv('action.csv', chunksize=10000)

chunks = []                    # 准备一个空列表,用来装每一块数据
for chunk in data:             # 遍历每一块
    chunk = pd.DataFrame(chunk)  # 转成DataFrame格式
    chunks.append(chunk)         # 把这一块塞进列表里

# 把所有小块拼成一个大表(就像拼积木一样)
action = pd.concat(chunks)

# 只保留我们需要的5列,其他的不要(省内存)
action = action[['user_id', 'sku_id', 'time', 'type', 'cate']]

为什么要分块? 1300万行数据直接读可能占500MB+内存,电脑容易卡。分块读取虽然代码多一点,但稳!

1.3 看看数据长什么样

action.info()

输出结果告诉我们:

  • 总共 13,199,934 行(1300多万条行为记录)
  • 5列:user_id(用户ID)、sku_id(商品ID)、time(时间)、type(行为类型)、cate(品类)
  • 占用内存约 503.5 MB

二、数据清洗:脏数据得收拾干净

数据清洗是分析的第一步,就像做菜前要洗菜一样。

2.1 检查空值

action.isnull().sum()

结果:5列都是0空值,数据还算干净,不用填空。

2.2 检查重复值

action.duplicated().sum()
# 结果:7262534(726万条重复!超过一半是重复的)

2.3 删除重复行

# inplace=True 表示直接在原表上改,不用重新赋值
action.drop_duplicates(inplace=True)

726万条重复数据! 删完之后只剩593万条,说明原始数据质量堪忧,清洗这步绝对不能省。

2.4 检查异常值

action.describe()

看统计摘要,检查有没有离谱的值(比如负数的用户ID、超大的时间戳等),这里数据还算正常。

2.5 处理字段类型

# user_id从浮点数转成整数(用户ID不该有小数点)
action['user_id'] = action['user_id'].astype('int64')

# time从字符串转成时间格式(转完才能做时间计算)
action['time'] = pd.to_datetime(action['time'])

action.head()
user_id sku_id time type cate
287842 75018 2016-03-31 23:59:01 6 9
208266 31662 2016-03-31 23:59:04 1 8
209390 118799 2016-03-31 23:59:05 6 8

三、特征提取:找出"高潜用户"

高潜用户 = 最有可能复购的用户。我们的思路是:找到那些购买时间距首次交互时间较长的用户,说明他们深思熟虑后才买,这类用户更容易复购。

3.1 理解行为类型(type字段)

action['type'].unique()
# 结果:array([6, 1, 4, 2, 3, 5])

action['type'].value_counts()
type 数量 含义(推测)
6 326万 浏览(最多,大家都在逛)
1 241万 点击
2 15万 加购物车
3 7万 删购物车
5 2.2万 收藏
4 1.2万 购买(最少,真正掏钱的)

3.2 只看"购买"行为

# type==4 就是购买行为,把购买记录单独拎出来
action_type4 = action[action['type'] == 4]
action_type4.head()

3.3 只分析品类4(简化分析)

# 为了方便理解,只筛选一个品类来分析
# 实际工作中可以分析所有品类,这里只是演示
action_type4 = action_type4[action_type4['cate'] == 4]
# 结果:2764条购买记录

3.4 找出每个用户最近一次购买时间

# 按user_id分组,取每组的最大时间(就是最近一次购买时间)
ac_lastbuytime = action_type4.groupby(by='user_id')['time'].apply(lambda x: x.max())
ac_lastbuytime.head()
user_id 最近购买时间
200053 2016-04-13 20:16:00
200054 2016-04-14 08:22:00
200092 2016-04-04 09:29:00

3.5 找出每个用户最早与商品的交互时间

# 把"最近购买时间"和"全部行为数据"合并,这样就能知道每个用户的所有行为
ac_all_buy = pd.merge(ac_lastbuytime, action, on='user_id')

# 按user_id分组,取最小时间(就是最早一次交互时间)
ac_firsttime = ac_all_buy.groupby('user_id')['time_y'].apply(lambda x: x.min())

3.6 计算时间差——核心指标!

# 把"最近购买时间"和"最早交互时间"合并到一张表
df = pd.merge(ac_lastbuytime, ac_firsttime.to_frame(), on='user_id')
df.columns = ['buytime', 'ac_time']  # 改个好看的名字

# 计算天数差:购买时间 - 首次交互时间
df['days'] = (pd.to_datetime(df['buytime']) - pd.to_datetime(df['ac_time'])).dt.days
df.head()
user_id buytime ac_time days
200053 2016-04-13 20:16:00 2016-04-01 18:16:48 12
200054 2016-04-14 08:22:00 2016-04-07 13:25:56 6
200092 2016-04-04 09:29:00 2016-04-01 08:48:09 3

days是什么意思? 比如用户200053,4月1号第一次浏览商品,4月13号才下单,中间隔了12天。这个天数越长,说明用户决策越谨慎。

3.7 筛选高潜用户

# 筛选时间差>1天的用户(交互超过1天才购买的,就是高潜用户)
high_pot = df[df['days'] > 1]
high_pot
# 结果:1882个高潜用户(总共2364个购买用户中)

为什么选>1天? 当天就买的用户可能是冲动消费,不容易复购;想了一两天以上才买的,更可能成为忠实用户。


四、合并用户画像数据

现在我们有了高潜用户列表,还需要知道这些用户的年龄、性别、等级等信息。

4.1 读取用户数据

# 读取用户基本信息表
user = pd.read_csv('user.csv')
user.head()
user_id age sex user_lv_cd browse_num addcart_num delcart_num buy_num favor_num click_num
200001 6.0 2.0 5 212.0 22.0 13.0 1.0 0.0 414.0
200002 -1.0 0.0 1 238.0 1.0 0.0 0.0 0.0 484.0

字段含义:

  • age:年龄段编码(-1表示未知,数字越大年龄越大)
  • sex:性别(0/1/2,其中0可能是女性居多)
  • user_lv_cd:用户等级(1-5,5最高)
  • browse_num:浏览次数
  • addcart_num:加购次数
  • delcart_num:删购次数
  • buy_num:购买次数
  • favor_num:收藏次数
  • click_num:点击次数

4.2 检查数据质量

user.shape
# (105321, 10)  -- 10万+用户,10个字段

user.isnull().sum()
字段 空值数
user_id 0
age 3
sex 3
browse_num 141
addcart_num 141
... 141
# 看看空值占比
user.isnull().mean()
# 空值最多只占0.13%,千分之一,影响很小

4.3 删除空值

# 空值占比千分之一,对结果影响较小,直接删除
user.dropna(inplace=True)

4.4 合并高潜用户和行为数据

# 用user_id做关联,把用户信息和购买时间差合并到一起
user_high = pd.merge(user, high_pot, on='user_id')
user_high
# 结果:1882行 × 13列

# 保存一份,方便后续使用
user_high.to_csv('user_high.csv')

五、可视化分析:用图表说话

数据准备好了,开始画图!我们用 pyecharts 和 Plotly 两种工具来画。

5.1 用户等级占比(饼图)

# 先统计各等级的人数
user_lv_count = user_high['user_lv_cd'].value_counts()
user_lv_count
# 等级5: 1187人, 等级4: 545人, 等级3: 147人, 等级2: 3人

用pyecharts画饼图:

from pyecharts.charts import *
import pyecharts.options as opts

# 准备数据:把等级和人数配对
num = user_lv_count.values.tolist()      # [1187, 545, 147, 3]
lev = user_lv_count.index.tolist()       # [5, 4, 3, 2]

# 配对成 [("等级5", 1187), ("等级4", 545), ...] 的格式
data_pair1 = [("等级" + str(i), j) for i, j in zip(lev, num)]

# 画饼图
pie = (
    Pie()
    .add("占比", data_pair=data_pair1)   # 填入数据
    .set_global_opts(
        tooltip_opts=opts.TooltipOpts(is_show=True, formatter='{b}:{d}%'),  # 鼠标悬停显示百分比
        title_opts={'text': '高潜用户各等级占比'}   # 标题
    )
)
pie.render_notebook()

洞察: 等级5的用户占63%(1187/1882),说明高潜用户以老用户为主,这很合理——等级越高越信任平台,复购意愿越强。

5.2 年龄分布(柱状图)

# 统计各年龄段人数
user_age_count = user_high['age'].value_counts()
# 年龄3.0: 1012人, 年龄4.0: 485人, 年龄-1.0: 169人, 年龄2.0: 136人, 年龄5.0: 57人, 年龄6.0: 23人

用pyecharts画柱状图:

from pyecharts.globals import ThemeType

bar = (
    Bar(init_opts=opts.InitOpts(theme='white'))   # 白色主题,干净清爽
    .add_xaxis(user_age_count.index.tolist())      # x轴:年龄段
    .add_yaxis('年龄分布', user_age_count.values.tolist())  # y轴:人数
)
bar.render_notebook()

洞察: 年龄段3和4的用户最多(占近80%),这是平台的消费主力人群。-1是未知年龄,也有169人。

5.3 性别分布(圆环图)

# 统计各性别人数
user_sex_count = user_high['sex'].value_counts()
# 性别0: 984人, 性别2: 751人, 性别1: 147人

# 配对数据
data_pair2 = list(zip(user_sex_count.index.tolist(), user_sex_count.values.tolist()))

用pyecharts画圆环图:

pie2 = (
    Pie()
    .add("占比", data_pair=data_pair2, radius=['30%', '60%'])  # 内半径30%,外半径60%,就是圆环(甜甜圈)效果
    .set_global_opts(
        tooltip_opts=opts.TooltipOpts(is_show=True, formatter='{b}:{d}%'),
        title_opts={'text': '高潜用户性别占比'}
    )
)
pie2.render_notebook()

5.4 年龄分布直方图(Plotly版)

import plotly.express as px

# 直方图能更精细地看到年龄的分布情况
fig = px.histogram(
    user_high,
    x='age',              # x轴:年龄
    nbins=20,             # 把数据分成20个区间
    title='用户年龄分布',   # 标题
    labels={'age': '年龄'}, # 轴标签
    height=500
)
fig.show()

5.5 性别分布圆环图(Plotly版)

fig = px.pie(
    user_high,
    names='sex',          # 按性别分组
    title='用户性别分布',
    labels={'sex': '性别'},
    height=500,
    hole=0.5              # hole=0.5就是在中间挖个洞,变成甜甜圈图
)
fig.show()

六、总结:用户画像分析的核心思路

整个分析流程可以概括为以下几步:

原始数据 → 数据清洗 → 特征提取 → 用户分群 → 可视化洞察

关键发现

维度 发现 业务建议
用户等级 等级4-5占92% 高潜用户以老用户为主,重点维护老用户关系
年龄 年龄段3-4占80% 这是消费主力,针对这个年龄段做精准营销
性别 性别0占52%,性别2占40% 两大性别群体都需要关注,可做差异化推荐
决策周期 平均决策天数较长 高潜用户偏理性消费,内容营销比促销更有效

分析方法总结

  1. 分块读取大文件pd.read_csv(chunksize=N) + pd.concat()
  2. 数据清洗三件套isnull() 查空值 + duplicated() 查重复 + describe() 查异常
  3. 分组聚合groupby() + apply(lambda x: x.max/min()) 找最值
  4. 表合并pd.merge() 按关键字段关联多张表
  5. 时间差计算(time1 - time2).dt.days 算天数差
  6. 可视化:pyecharts画交互式图表,Plotly画快速探索图

更多推荐