
简介这套Python用户画像构建源码基于Jupyter Notebook环境编写主要面向数据分析初学者和产品运营人员解决如何从原始用户数据出发完成清洗、特征提取、行为分析与画像可视化的问题。资源包共含20个文件包括13份CSV数据文件、4个Notebook代码文件、1个独立Python脚本、1张PNG示意图和1份Markdown说明文档压缩包整体大小约118.46MB。CSV文件中存放用户基础信息与行为记录Notebook以分步代码演示完整分析流程借助Pandas等库进行数据处理并通过Matplotlib或Seaborn绘制图表独立py模块可用于数据清洗和特征整合PNG图则直观展示画像结果或流程图解。目前已有125人学习下载。获取后可按Markdown文档中的设计思路逐步运行Notebook理解每个环节的代码逻辑也可以复用自带数据修改函数参数与可视化配置快速迁移至自己的用户分析场景中。1. 用户画像构建源码拆解为什么泰坦尼克号是理解这套工程的最佳入口用户画像构建听起来是个业务味很重的词但这套基于Jupyter Notebook的Python源码把它落到了实处13个CSV数据文件是原料4个Notebook是执行引擎配合一个Python源文件和一个PNG可视化输出串起了一条完整的数据分析链路。我拆这套工程时发现一个很妙的安排——目录里专门放了一个泰坦尼克号数据挖掘流程这是Kaggle上最经典的入门项目作用就是让你先跑通数据清洗 → 特征工程 → 建模 → 结果输出这条标准流水线再把同样的方法论平移到用户画像构建上。适合刚接触数据分析与用户画像的Python学习者也适合想复用一套成熟流程做用户行为分析的从业者。2. 源码结构与运行环境20个文件如何组成一条完整的画像构建链路拿到压缩包后不要急着双击Notebook先把目录结构过一遍。这套源码一共20个文件目录分成01泰坦尼克号和02用户画像两个区块前者是方法演示后者是业务落地两者通过同一套pandas处理习惯衔接。2.1 文件清单逐项拆解CSV、Notebook、Python模块和Markdown的分工我习惯把文件按输入 → 处理 → 输出三个位置摆开看这套工程的文件刚好能对上这条链路文件类别数量在流水线里的角色CSV数据文件13原始数据输入包含训练集、测试集与用户行为表IPython Notebook4数据处理、分析与画像构建的主体执行文件PNG图像1可视化输出结果通常是分析图表或流程示意Python源文件1抽离出的公共函数供Notebook调用复用Markdown文档1设计思路、字段口径与使用说明注意每个Notebook目录下都带一个.ipynb_checkpoints文件夹这是Jupyter Notebook自动生成的检查点目录每隔一段时间会自动保存一份当前编辑状态。它不是源码的一部分分享或提交版本管理时需要忽略掉。CSV文件是这套工程的原料层。泰坦尼克号目录下的train.csv和test.csv是模型训练和预测的标准切分用户画像目录下的CSV则承担了用户行为记录和基础属性信息。Notebook文件是核心加工层我翻看这套工程时注意到它遵循了典型的数据分析节奏先用pandas做数据探查再用Matplotlib或Seaborn出图最后落到结论或标签。那个Python源文件的作用值得单独说一下。当你在Notebook里写了一段清洗逻辑发现另一个Notebook也要用最省事的做法是把它抽成一个.py模块在主程序里import调用。这套工程里的Python源文件扮演的就是这个角色它能避免你在多个Notebook里复制粘贴同一段代码也方便单独做单元测试。2.2 环境搭建用conda装好Jupyter Notebook与pandas生态网上搜python安装教程会看到各种版本建议我的建议始终是用conda创建独立环境不要往系统Python里乱装包。用户画像构建依赖的数据栈是pandas、Matplotlib、Seaborn、scikit-learn这些包对版本组合有要求混在系统环境里很容易出现依赖冲突。conda create -n user_profile python3.9 -y conda activate user_profile pip install jupyter pandas matplotlib seaborn scikit-learn逻辑说明第一行创建名为user_profile的独立虚拟环境Python版本锁定3.9。这个版本对pandas 2.x和scikit-learn 1.x兼容性最好网上很多jupyter notebook安装教程没提版本直接装最新Python反倒容易踩到二进制包还没适配的坑。第二行激活环境第三行用pip一次性安装五个核心库。参数说明python3.9指定解释器版本不要省略如果你机器上已经有Python 3.10或3.11也可以尝试但遇到某个库没有预编译wheel包时需要退回源码编译。安装完成后在终端确认一下版本python -c import pandas; print(pandas.__version__)如果输出版本号没有报错说明pandas安装成功。这套源码在设计时默认你具备基础的Jupyter Notebook操作能力所以接下来要做的是把内核和虚拟环境绑定而不是直接使用默认的Python 3内核。2.3 内核绑定让Notebook跑在指定的Python解释器上新手最容易翻车的地方就在这里明明在conda环境里装好了pandas打开Jupyter Notebook后import pandas却报ModuleNotFoundError。原因很简单Jupyter Notebook默认启动的是base环境里的Python而不是你激活的那个conda环境。解决方法是把当前虚拟环境注册成Notebook的一个内核。conda activate user_profile python -m ipykernel install --user --name user_profile --display-name Python (user_profile)参数说明--name是内核的标识名必须跟环境名对应否则容易混淆--display-name是你在Notebook界面上看到的名字可以随意起方便识别就行。执行成功后重启Jupyter Notebook在页面的Kernel → Change kernel菜单里选择Python (user_profile)再执行import pandas就不会报错了。这个步骤做完环境就彻底闭环了。下一步才是真正进入数据分析流程——先跑通泰坦尼克号这个标准案例。3. 泰坦尼克号数据挖掘流程一套可直接迁移到画像场景的完整范式泰坦尼克号数据集之所以经典是因为它具备一个真实数据分析项目的所有要素有缺失值、有分类特征、有数值特征、有明确的预测目标Survived。这套源码用它演示的是一整套流程不是某个单点技巧迁移到用户画像场景时你只需要替换数据源和目标字段。3.1 数据探索从train.csv到字段盘点与缺失值处置打开01泰坦尼克号目录下的数据挖掘流程Notebook第一步一定是读数据。我用常见的数据分析流程还原这套源码的核心思路import pandas as pd train pd.read_csv(train.csv) test pd.read_csv(test.csv) train.info()逻辑说明train.info()用来查看每列的字段类型和非空值数量这一步比head()更重要因为缺失值的分布直接决定后续特征工程怎么做。泰坦尼克号数据集的字段是公开标准的train.csv包含PassengerId、Survived、Pclass、Name、Sex、Age、SibSp、Parch、Ticket、Fare、Cabin、Embarked共12列test.csv比训练集少Survived标签列。运行info()之后你会看到Age和Cabin的非空数量明显少于总行数这就是缺失值信号。常见做法是先对缺失情况做一次统计missing_rate train.isnull().mean().sort_values(ascendingFalse) print(missing_rate[missing_rate 0])参数说明isnull().mean()是pandas里计算缺失率最简洁的写法返回每列缺失百分比。过滤出缺失率大于0的列能一眼看清处理优先级。泰坦尼克号场景下Cabin缺失率超过70%一般直接丢弃Age缺失约20%通常用中位数填充Embarked只有两个缺失值用众数填充即可。这里的取舍逻辑你要记住它会直接平移到用户画像数据上缺失率过高的字段对模型是噪声而非信号果断删缺失率适中的连续字段用中位数而非均值填充因为均值对离群值敏感。3.2 特征工程与可视化用Seaborn确认特征的区分度填完缺失值先别急着建模先画图。用Seaborn看看每个特征跟预测目标Survived的关系这是判断特征有没有解释力的最快手段。import seaborn as sns import matplotlib.pyplot as plt sns.barplot(datatrain, xPclass, ySurvived) plt.ylim(0, 1) plt.show() sns.barplot(datatrain, xSex, ySurvived) plt.ylim(0, 1) plt.show()逻辑说明barplot的横轴是特征类别纵轴是该类别下的生存率均值。从图上能直观看到头等舱生存率明显高于三等舱女性生存率显著高于男性。这两个特征对预测目标有真实区分度是建模阶段的首选特征。参数说明plt.ylim(0, 1)把纵轴固定到全区间避免图形比例误导plt.show()在Notebook里是必须的否则图像可能不刷新。你还可以用sns.countplot(datatrain, xEmbarked, hueSurvived)做分组计数对比看登船口岸的影响。关于PNG图像这套源码里那张PNG大概率就是这一步产生的。保存图片时我一般会加两行参数避免图片发白或截断plt.tight_layout() plt.savefig(../img/pclass_survived.png, dpi150)dpi150是屏幕和文档兼顾的分辨率bbox_inchestight也能加专门对付坐标轴标签被截断的问题。特征工程阶段用图形辅助判断比直接跑模型再解释特征重要性直观得多。3.3 建模与验证逻辑回归基线与交叉验证特征看完建模就很顺了。泰坦尼克号是二分类问题逻辑回归是标准基线from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score features [Pclass, Sex, Age, SibSp, Parch, Fare] X train[features].copy() X[Sex] X[Sex].map({male: 0, female: 1}) X[Age] X[Age].fillna(X[Age].median()) model LogisticRegression(max_iter500) scores cross_val_score(model, X, train[Survived], cv5) print(fCV accuracy: {scores.mean():.4f})逻辑说明Sex需要从文本映射成数值male转0、female转1这是sklearn的要求。Age的缺失值必须在建模前再次确认填充否则sklearn会直接报错。cross_val_score做了5折交叉验证比单次train_test_split更稳。参数说明max_iter500是逻辑回归的迭代上限默认100在某些数据分布下会不收敛报ConvergenceWarning调大这个参数能消除警告。cv5表示分割成5份做交叉验证是工业界的习惯值。交叉验证输出的均值如果在0.78到0.83之间说明这个基线是健康的——太高要怀疑数据泄露太低要回查特征工程。建模到这里就够了泰坦尼克号的价值在于流程示范不在于刷精度。真正的重头戏在用户画像部分那才是这套源码的落点。4. 用户画像构建实战把用户行为数据加工成可解释的画像标签用户画像构建的核心不是算法而是把业务理解翻译成数据加工步骤。泰坦尼克号教给你的数据探索和可视化方法在这里原样复用只是目标从预测生存率变成了给用户打标签。4.1 标签体系设计从原始行为字段到画像维度的映射用户画像部分的CSV数据没有泰坦尼克号那么标准的字段命名不同行业的用户表差异很大常见的有用户信息表、订单表、行为日志表。我一般会先看一眼字段名再反向定义标签体系。这套源码的标签维度大概可以分成四类画像维度标签示例数据来源基础属性性别、年龄段、城市等级用户信息表消费能力高/中/低客单、近30天消费金额订单表行为偏好品类偏好、活跃时段行为日志表活跃度高/中/低频用户、流失风险行为日志表标签体系设计要走在代码前面。我的习惯是在Notebook第一个单元格里用Markdown把这四行写出来明确每个标签对应哪个CSV文件的哪个字段避免做到一半回头改口径。从原始字段到标签的映射不是简单字段复制。比如消费能力这个标签原始表里可能只有订单金额amount你需要通过聚合计算出每个用户的客单价再分箱成高/中/低。活跃度则需要时间戳字段统计用户在观察窗口内的登录或下单频次。这一步是用户画像构建的关键也是这套源码对比泰坦尼克号流程新增的核心内容。4.2 用户行为分析用pandas实现RFM分桶与活跃度统计RFM模型是用户行为分析最经典的方法三个维度分别是最近一次消费时间Recency、消费频率Frequency、消费金额Monetary。它对应的正是标签体系里的活跃度和消费能力。import pandas as pd orders pd.read_csv(user_orders.csv, parse_dates[order_date]) ref_date orders[order_date].max() pd.Timedelta(days1) rfm orders.groupby(user_id).agg( recency(order_date, lambda x: (ref_date - x.max()).days), frequency(order_date, count), monetary(amount, sum) ) rfm[recency_bin] pd.qcut(rfm[recency], 4, labels[R4, R3, R2, R1]) rfm[frequency_bin] pd.qcut(rfm[frequency].rank(methodfirst), 4, labels[F1, F2, F3, F4])逻辑说明parse_dates[order_date]在读取时就把日期列解析成datetime类型避免后续字符串比较的坑。ref_date设为数据中最大日期加一天这样计算recency时不会出现0天或负数。groupby(user_id).agg()一次算出三个指标最近一次消费距今的天数、消费次数、累计消费金额。参数说明pd.qcut按分位数等频分桶labels[R4, R3, R2, R1]给每个桶命名R4表示最近刚来过R1表示很久没来。这里有个容易踩的坑qcut要求分箱边界唯一如果frequency列有大量重复值比如很多人只下单1次直接分桶会报Bin edges must be unique。解决的常见做法是先对frequency做rank(methodfirst)把并列值拆开再进行分位数切分。这三个指标算完每个用户就拿到了recency_bin和frequency_bin两个画像标签再按业务需求给monetary分箱就能组合出高价值活跃用户流失风险用户这类复合标签。4.3 画像结果输出从DataFrame到PNG文件的可视化落地画像标签是离散的最适合用图形展示分布。这套源码里的PNG图片和img目录承担的就是这个输出落地功能。import matplotlib.pyplot as plt from matplotlib import rcParams rcParams[font.sans-serif] [SimHei] rcParams[axes.unicode_minus] False profile_summary rfm.groupby([recency_bin, frequency_bin]).size().unstack() profile_summary.plot(kindbar, figsize(10, 6)) plt.title(用户活跃度分群分布) plt.xlabel(最近消费分桶) plt.ylabel(用户数) plt.tight_layout() plt.savefig(../img/user_profile_distribution.png, dpi150) plt.show()逻辑说明groupby([recency_bin, frequency_bin]).size().unstack()生成一个行列都是分桶标签的透视表plot(kindbar)直接画出堆叠的分组柱状图。savefig把图形保存到img目录这就是源码中PNG文件的来源。参数说明rcParams[font.sans-serif] [SimHei]是中文显示的关键不加这一行坐标轴上的中文标签会显示成方框。axes.unicode_minusFalse解决负号显示问题。dpi150保证图片在报告中放大也不模糊。到这里用户画像构建的主流程已经完整跑通。但从我实操的经验看复现这套源码时真正耗时间的不是业务逻辑而是一堆环境相关的小问题。5. 复现与排查避坑路径、编码、内核绑定的高频翻车点这套源码我前后在不同机器上跑过几次每次都遇到几个固定问题。这里整理成现象、原因、解决三段式希望能帮你少走弯路。5.1 FileNotFoundError工作目录与相对路径的陷阱现象按照Notebook里的代码执行pd.read_csv(train.csv)报FileNotFoundError而文件明明就在同行目录下。原因Jupyter Notebook的工作目录不是Notebook文件所在目录而是你启动jupyter notebook命令时所在的终端目录。如果你在用户主目录启动再通过文件树点进01泰坦尼克号目录打开Notebook代码里的相对路径会基于主目录解析自然找不到文件。解决先执行import os; print(os.getcwd())确认当前工作目录然后统一在工程根目录启动Jupyter。更稳的做法是代码开头强制切换import os os.chdir(/path/to/your/project)血泪经验是拿到任何一套源码第一步都先看工作目录别一上来就跑单元格这一步能消除一半以上的路径报错。5.2 中文CSV乱码编码探测与encoding参数现象读取用户画像的CSV文件后中文列名或内容显示成锟斤拷之类的乱码严重时直接抛UnicodeDecodeError。原因CSV文件的编码不是默认的UTF-8而是GBK或GB2312。Windows平台导出的数据表尤其常见而pandas默认按UTF-8读取。解决先指定GBK编码读取df pd.read_csv(user_info.csv, encodinggbk)如果还是报错用chardet探测真实编码import chardet with open(user_info.csv, rb) as f: result chardet.detect(f.read()) print(result[encoding])这不是玄学是标准排查路径。探测结果可能是GB2312或BIG5把它填进encoding参数就行。5.3 内核不一致Notebook里import不到刚装好的库现象在终端执行python -c import pandas不报错但Notebook里执行import pandas报ModuleNotFoundError。原因Jupyter Notebook选用的Python内核不是当前conda环境。这是环境变量和内核注册表的经典错位很多刚接触Python环境的人在这里翻车。解决按第2.3节的命令重新注册内核然后在Notebook菜单Kernel → Change kernel中选对内核。查看当前内核执行jupyter kernelspec list如果列表里没有user_profile说明内核注册失败重新执行python -m ipykernel install --user --name user_profile即可。5.4 列名语义漂移同名不同义的跨表合并现象用pd.merge合并两张表后行数暴涨或者画像标签跟原始数据对不上。原因两张表都有user_id但一张是整数类型int64另一张是字符串类型objectmerge时类型不匹配导致结果异常。更隐蔽的是两张表的user_id含义不同一张是注册ID另一张是设备ID。解决合并之前先检查类型和样本print(orders[user_id].dtype, users[user_id].dtype) print(orders[user_id].head(3)) print(users[user_id].head(3))确认类型不同就强制统一orders[user_id] orders[user_id].astype(str) users[user_id] users[user_id].astype(str)这一步看起来基础但在用户画像构建中字段口径不一致是数据质量问题的大头值得多花几分钟核对。5.5 .ipynb_checkpoints污染检查点文件带来的不一致现象明明改了Notebook里的代码重新运行后结果还是旧的或者git提交时看到一堆.ipynb_checkpoints目录的变更。原因Jupyter Notebook会自动把检查点保存到.ipynb_checkpoints目录这个目录里的文件是旧版本快照。如果分享源码时没清理别人打开的可能不是最新逻辑。另外Notebook底层是JSON格式部分检查点文件在并发写入时可能损坏。解决分享前执行清理rm -rf .ipynb_checkpoints同时把.ipynb_checkpoints/写进.gitignore从根上避免它被提交。用jupyter nbconvert --to notebook --execute --inplace your.ipynb重新执行并覆盖当前文件也能保证Notebook内容与输出一致。6. 进阶用法把泰坦尼克流程改造成自动化的画像更新流水线泰坦尼克号是一次性分析用户画像却是要持续更新的业务资产。如果你已经在这套源码上跑通了全流程下一步就是把它从手动操作改造成自动化流水线我的做法是分三步走。第一步把Notebook里的数据清洗函数抽到那个Python源文件里。泰坦尼克流程里的缺失值填充、用户画像部分的RFM计算都写成独立函数统一放在profile_utils.py里。Notebook只负责读数据、调函数、画图这样任何一处口径变了只改一处代码。第二步用命令行批量执行Notebook让画像更新变成一条命令的事jupyter nbconvert --to notebook --execute --inplace 02用户画像/*.ipynb这段命令会按顺序执行用户画像目录下所有Notebook--inplace参数把执行结果写回原文件--execute强制重新运行所有单元格。跑完后数据表和PNG图片自动更新对应的Markdown报告手动补充解读即可。第三步给画像质量设一个检查点。我一般会写一个简单的验证函数跑完流水线后检查三件事分桶标签是否有空值、用户总量是否在合理波动范围、新用户是否正常进入画像表。过了检查点才认为这次画像更新是成功的。这套源码的readme.txt里如果写了字段口径说明正好可以拿来当检查标准的依据。从那以后我每次搭画像工程都会先强制走一遍这个流程编好文件清单、锁死环境版本、写字段口径文档最后才是写代码跑数据。顺序乱了后面一定会回头补账。希望帮到你。本文还有配套的精品资源点击获取