电商用户行为数据分析:从数据清洗到转化漏斗的完整实践指南
发布时间:2026/9/30 3:24:16来源:尧图网络
第五次作业拿到手的时候我其实是有点慌的。前面四次作业我基本都在数据清洗环节耗掉大半时间最后交上去的分析结论却被老师批了仨字太浅。这次是电商用户行为数据分析课的大作业要拿一份接近千万条的用户行为日志完整跑通从数据清洗、特征理解到转化漏斗分析、用户分层建议的闭环。说实话做到第五次才算真正摸到点门道分析类作业和写代码类作业完全是两码事前者考验的是业务理解后者只是验证你会不会调用某个函数。这篇就把我这轮作业的思路拆解、关键代码、踩坑记录和复盘心得全部摊开来聊聊适合正在做类似数据分析作业、或者想系统过一遍用户行为分析流程的同学参考。1. 作业要求与设计思路拆解1.1 这次作业到底要解决什么问题先把作业背景交代清楚。这次拿到的数据集来自某电商平台的用户行为日志一共 9,876,543 条记录字段包括用户ID、商品ID、品类ID、行为类型、行为时间、设备类型、会话ID。行为类型一共四种pv 表示浏览商品页fav 表示收藏cart 表示加入购物车buy 表示支付购买。作业要求分三块第一完成一份完整的数据清洗记录说明每一步处理了什么、为什么这么处理第二计算整体用户行为转化漏斗并按设备类型和时段两个维度拆解找出转化差异最明显的环节第三基于分析结果给出至少两条可落地的运营建议每条建议都要能对应到具体的漏斗环节而不是空泛地说“提升用户体验”。我把这次作业当成一次完整的数据分析小项目来做而不是单纯交作业。在实际项目里最忌讳的事情就是拿到数据就开始写代码写到哪算哪。所以我做的第一件事不是跑df.describe()而是先把作业要求拆成一张需求清单明确自己要交付什么、用什么指标去衡量、每个分析结果最终要支撑什么结论。作业要求我对应的分析方案关键输出数据清洗记录字段检查、去重、缺失值处理、异常值甄别清洗后的数据集 处理说明整体转化漏斗按用户去重统计 pv/cart/fav/buy计算相邻步骤转化率漏斗表 流失环节判断分设备差异分析按设备类型 行为类型交叉统计对比转化率设备对比表 结论分时段差异分析按小时统计活跃度与购买转化率时段热力表 运营建议运营建议基于漏斗最弱环节 差异维度交叉定位2 条以上可落地方案这份清单看起来简单但它决定了后面所有代码怎么写。如果没有它我大概率又会在数据清洗环节陷进去花两天时间处理一些对最终结论毫无影响的细节。1.2 为什么选择“漏斗分层”这套思路分析方案我最终定为“漏斗模型 维度分层”。逻辑其实很简单用户行为日志记录的是一个个离散的行为事件如果不把它们串成一条路径数据就只是一堆数字一旦按“浏览 → 加购 → 支付”的行为顺序去统计就能直观看到每一步流失了多少人哪个环节最需要干预。漏斗模型的优势在于解释性强。相比跑一个复杂的机器学习模型漏斗的结果可以直接翻译成业务语言“从加购到支付的转化率只有 12%说明用户在结算环节流失严重”这句话任何业务方都能看懂。同时单一漏斗太过宏观看不出差异在哪里所以必须叠加分层维度。我选了设备类型和时段两个维度因为这两个维度最容易对应到运营动作和投放策略。这套思路也帮我避开了作业里最常见的坑只用总量指标。只看整体转化率你永远回答不了“为什么转化率低了”拆到设备、时段、品类之后问题才变得可定位。我后续所有分析都是在一个总的漏斗框架下展开的。2. 数据准备与清洗先看清楚再动手2.1 数据字典比代码更重要这次拿到数据之后我忍住了直接pd.read_csv()的冲动先做了一件事写数据字典。把每个字段的含义、类型、缺失情况、潜在问题全部记下来。听起来很基础但前面几次作业我都是跳过这一步直接处理结果后面反复回头查字段含义浪费了大量时间。我的检查流程是这样的先读入一小部分数据看结构然后逐个字段统计唯一值数量、缺失数量、样例值。重点看两个容易出问题的字段action_time是字符串还是时间类型不同的时间格式会直接影响后续分组统计action字段看似只有四个值但实际数据里可能混入大小写不一致、前后带空格、甚至未知行为类型必须提前确认。字段类型缺失情况需要注意的问题user_idint无是否唯一一个用户可能多条记录product_idint无商品 ID 范围后续是否需要过滤category_idint无品类数量用于分层分析actionstr无值是否只有 pv/fav/cart/buy大小写是否一致action_timestr无格式是否统一是否需要解析成时间类型device_typeint少量缺失缺失值如何处理session_idint无一个会话可能包含多个行为把这张表整理完我对整个数据集的结构就有数了。这一步花了我大约半小时但后面每一段分析代码都因此写得非常顺畅不再需要反复去猜字段含义。2.2 清洗中的四个关键取舍数据清洗看着繁琐其实核心就是做取舍。这次作业我处理了四个问题每个都记录下了选择原因和影响范围。第一个是重复记录。我最初按行去重后发现重复率不到 0.3%但如果直接删掉所有完全重复的行可能会误删用户在同一秒内对同一商品产生的连续有效行为。最终我的取舍是只保留“同一用户、同一商品、同一行为、60 秒内出现多次”的重复记录中的第一条其余保留。这样既去掉大多数重复点击又不会影响真实连续操作。第二个是缺失值。device_type字段存在约 1.2 万条缺失记录占比很小。我观察了缺失样本的其他字段分布发现缺失情况在各个时段都存在没有明显的倾向性所以用众数填充是合理的。但如果缺失比例超过 10%就必须评估填充是否会造成偏差而不是机械地填一个值。第三个是异常值。数据里出现了少量“只有 buy 行为、完全没有对应 pv/cart 记录”的用户。这里要谨慎这些可能是通过外链直接下单也可能是数据采集缺失。我的处理不是直接删除而是单独打标签保留在分析漏斗时单独看这批用户的占比。结果显示这类用户只占 0.8%不影响整体结论。第四个是时间字段。原始action_time是带毫秒的字符串我先统一格式再转成 datetime避免后续按小时分组时出错。转完之后我又做了个校验确认没有出现 1970 年之类的初始时间值说明没有严重的时区或格式化问题。清洗步骤全部记录在一个 Jupyter Notebook 里每一步都保留前后的数据量对比方便回溯。这也是后面写报告时候的重要素材作业要求里的“清洗记录”就可以直接复用这些内容。3. 核心指标计算与分析实现3.1 转化漏斗的构建与结果解读漏斗计算是整个作业的核心环节。这里有个容易犯的错误直接用行为次数做漏斗而不是用去重用户数。比如同一个人浏览了 20 次商品页如果按行为次数算他会被计入 20 次浏览严重扭曲转化率。所以我统一采用“每个环节只计算去重用户数”的方式。清洗完成后我先对整体漏斗做了统计核心代码如下import pandas as pd import numpy as np df pd.read_csv(user_behavior_clean.csv, parse_dates[action_time]) funnel_data ( df.groupby(action)[user_id] .nunique() .reindex([pv, fav, cart, buy], fill_value0) ) total_pv funnel_data[pv] total_buy funnel_data[buy] print(f各环节去重用户数\n{funnel_data}) print(f整体浏览到购买转化率{total_buy / total_pv * 100:.2f}%)结果如下表环节去重用户数相对上一环节转化率相对整体转化率pv 浏览682,314--fav 收藏132,46819.41%19.41%cart 加购254,31837.27%相对 pv37.27%buy 购买81,59232.09%相对 cart11.96%看到这个表最明显的结论是从浏览到加购的转化率只有 37%而收藏用户的体量明显小于加购用户说明用户更倾向于“先加购再看”收藏这个动作只是少数人的偏好。更关键的问题是从加购到支付的转化率只有 32%也就是说三分之二的加购用户最终没有完成购买。这时候大脑里的第一反应是“结算流程有问题”但如果只下这个结论作业还是太浅。要判断问题到底出在哪里必须继续拆分层维度。3.2 分设备分析同一个漏斗不同的人群整体漏斗只能告诉你“哪里漏了”解释不了“为什么漏”。接下来我按device_type拆开看把设备分为 PC、移动端、APP 三类同样计算各自的漏斗。device_funnel ( df.groupby([device_type, action])[user_id] .nunique() .unstack(fill_value0) .reindex(columns[pv, fav, cart, buy], fill_value0) ) device_funnel[pv_to_cart] device_funnel[cart] / device_funnel[pv] * 100 device_funnel[cart_to_buy] device_funnel[buy] / device_funnel[cart] * 100 device_funnel[pv_to_buy] device_funnel[buy] / device_funnel[pv] * 100 print(device_funnel)分设备数据让我对漏斗的认知一下子具体起来设备类型pv 用户数cart 用户数buy 用户数pv→cartcart→buypv→buyPC221,03899,39736,91444.97%37.14%16.70%移动端296,45191,31028,19430.80%30.88%9.51%APP164,82563,61121,56738.59%33.90%13.08%移动端的浏览用户数最大但两个关键转化率都是三类设备里最低的pv→buy 只有 9.51%比 PC 端低了 7 个百分点。这说明移动端用户量虽然庞大但决策质量不高可能是场景碎片化导致的。PC 端用户量最小转化率却最高典型的“少量但精准”人群。APP 端处在中间但它的浏览用户少说明 APP 的拉活或留存存在短板。这个发现直接对应到一个业务动作移动端的运营重点不是继续拉量而是想办法把碎片化的浏览转化成加购比如通过购物车提醒、限时优惠锁客等方式。PC 端的重点则是继续放大精准流量的触达同时优化结算体验因为它的加购到购买转化还有提升空间。3.3 分时段分析找流量节奏和运营窗口光有设备维度还不够因为运营动作需要知道什么时间点发力。我继续把action_time拆成小时维度统计每个小时的活跃用户数和购买转化率。df[hour] df[action_time].dt.hour hourly_stats ( df.groupby([hour, action])[user_id] .nunique() .unstack(fill_value0) .reindex(columns[pv, fav, cart, buy], fill_value0) ) hourly_stats[pv_to_buy] hourly_stats[buy] / hourly_stats[pv] * 100 hourly_stats[cart_to_buy] hourly_stats[buy] / hourly_stats[cart] * 100我重点看两个指标pv 的日变化曲线和 pv_to_buy 的高点时段。结果显示流量高峰集中在晚上 20 点到 23 点这个时段 pv 量达到全天峰值的 1.8 倍但有意思的是转化率最高的时段出现在上午 10 点到 12 点pv_to_buy 能到 14% 左右晚上高峰时段反而只有 10% 上下。这不难理解晚上的用户多为休闲场景随手翻商品的人多真正下单的少上午的用户目标感更强想买什么就是冲着下单来的。这个结论的价值在于运营活动不需要一味盯着流量高峰做上午的精准时段同样值得投入资源甚至因为竞争流量少投放的性价比更高。到这里整个分析的逻辑闭环形成了整体漏斗指出“加购→支付”是最弱环节分设备看移动端拖累了整体分时段看流量高峰与转化高峰错位。三个分析结果相互印证最后可以一起支撑运营建议的提出。4. 常见问题与排查技巧实录4.1 近千万行数据pandas 差点崩了第一个实际问题就是内存。983 万行数据如果全部按默认方式读入占用的内存大约 800MB 到 1GB我的电脑直接卡到鼠标都会漂移。前几次作业我都是咬着牙硬等这次学乖了用了几招就轻松解决。第一招是只读需要的列不需要的字段坚决不读进来。因为这次分析根本用不到商品描述类的字段我只保留了 bike 七个字段。第二招是压缩数据类型。user_id、product_id这些整数列实际取值范围远小于 int64我全部转成 int32 甚至 int8action这种取值固定的列转成 category 类型内存占用直接降一半以上。df pd.read_csv( user_behavior.csv, usecols[user_id, product_id, category_id, action, action_time, device_type, session_id], dtype{ user_id: int32, product_id: int32, category_id: int32, action: category, device_type: int8 }, parse_dates[action_time] )处理完之后内存占用从 900MB 降到不到 200MB整个分析过程流畅了很多。如果你的数据量比这还大可以考虑分块读取或者用pyarrow格式但这次作业完全用不上。4.2 转化率低得离谱先查分母这次作业我踩过一个特别经典的坑第一次算整体转化率浏览到购买只有 4.8%怎么看都不对。检查代码发现我用的是各个行为的总次数做分子分母而同一个用户可能浏览了十几次却只购买一次这会把分母撑得很大转化率自然被严重拉低。正确的做法是每个环节都用去重用户数作为统计口径也就是df.groupby(action)[user_id].nunique()。这里有个细节nunique()对缺失值敏感如果 user_id 有 NaN会被直接忽略所以清洗阶段必须确认 user_id 没有缺失否则统计结果会悄悄变小。另一个分母层面的问题计算“加购到购买”的转化率时分母应该是进入加购环节的用户数而不是全部浏览用户数。这是两个完全不同的指标前者衡量的是结算效率后者衡量的是整体漏斗效率混用会让分析结论失去解释力。4.3 时间字段的坑格式化、时区、空值时间字段是这次作业里最隐蔽的坑。原始数据的action_time是字符串格式里面既有2024-12-01 10:23:45也有带毫秒的2024-12-01 10:23:45.123和 UTC 后缀的格式三者混在一起。直接pd.to_datetime()虽然能转但有些行会被解析成 NaT后面分组就莫名其妙少了数据。我的处理是分两步先统一格式把毫秒和后缀直接去掉再做转换校验检查isna()的占比。如果发现大量 NaT马上回溯原始字符串看是不是有别的格式遗漏。转换完成之后我还会抽查几行样本确认时区没有导致小时数偏移。时间字段导致空值的问题排查思路其实很简单不要只看转换后的结果要回看转换前的原始值。有几次我只盯结果永远找不到空值来源后来把转换前字符串统计了一遍才发现是混入了2024/12/01这种斜杠格式。做数据分析最怕的就是数据爱你时格式千奇百怪。5. 这次作业我总结出的实操心得5.1 先画分析框架再写代码前四次作业最大的问题不是代码写不出来而是没想清楚“算这个指标到底干什么用”。这次我最大的改变是动手前先在纸上画了一份分析框架从上到下依次是目标、指标、维度、结论。每画一层都要问自己一个问题这个指标算出来之后能支撑我哪个结论想不清楚的指标直接砍掉。这个习惯让我的分析过程高度聚焦。后面写代码时我基本不会做多余的探索性操作每个分析步骤都对应最终报告里的一个模块代码量减少了不少但报告质量反而上来了。对于作业场景来说思路清晰比代码花哨重要得多。5.2 保留中间结果让每一步都可追溯这是我这次作业最受益的操作习惯。每次分组统计得到的结果我都会单独保存一份 CSV 或者直接存到变量里不覆盖上一步的输出。比如洗完数据保存一份user_behavior_clean.csv漏斗计算保存一份funnel_total.csv分设备和分时段的结果各保存一份。好处是当分析做到后面发现结论有问题时可以快速回溯是数据清洗的锅、还是指标口径的锅、还是某一步代码的锅。我实际排查“转化率过低”问题时就是因为保留了三版中间结果才在十分钟内定位到是口径问题而不是逐段重跑代码。做数据分析最贵的不是存储空间而是排查问题的时间。5.3 把分析结论翻译成业务动作作业要求最后要给出运营建议这也是我前几次被批“太浅”的地方。这次我把每个建议都对应到了具体的漏斗环节和维度上不让结论悬在半空。举个例子针对“移动端 pv→cart 转化率只有 30.80%”这个发现我建议在移动端商品详情页增加购物车按钮的曝光层级同时在用户连续浏览三个商品却未加购时主动推送一个限时加购优惠券。这条建议对应得极其具体有目标环节、有触发条件、有产品动作。另一个建议是针对“上午时段转化率高、晚上流量大”的错位我建议把爆款商品的限时秒杀安排在上午 10 点而不是晚上流量高峰期。虽然晚上流量大但转化率低同样的营销资源在上午能带来更高的 ROI。把分析结论落成这一步作业才真正有了价值。最后分享一个我这次作业里非常受益的小习惯每次算完一个指标先别急着写结论回原始数据里随机抽三个用户沿着他们的行为路径逐条看一遍。这个方法帮我发现了两处代码逻辑错误也让我在写报告时特别有底气。分析结果再漂亮经得起抽样验证才拿得出手。
网站建设高端定制企业官网