24. 数据分箱1. 概述数据分箱Binning是将连续变量离散化的过程将数值范围划分为多个区间每个区间称为一个箱。分箱常用于将连续变量转换为分类变量便于分析和建模。importpandasaspdimportnumpyasnp# 创建示例数据np.random.seed(42)dfpd.DataFrame({姓名:[f用户_{i}foriinrange(1,21)],年龄:np.random.randint(18,70,20),收入:np.random.randint(3000,30000,20),分数:np.random.randint(0,100,20),消费次数:np.random.randint(1,100,20)})print(原始数据:)print(df.head())2. cut() - 等宽分箱2.1 基本用法cut()将数据按指定的区间边界进行分箱。# 定义年龄区间age_bins[0,30,50,100]age_labels[青年,中年,老年]df[年龄段]pd.cut(df[年龄],binsage_bins,labelsage_labels)print(年龄段分布:)print(df[[年龄,年龄段]].head())# 查看各区间计数print(\n年龄段统计:)print(df[年龄段].value_counts())2.2 自动生成区间# 指定区间数量自动等宽分箱score_bins4# 分成4等份score_labels[低,中低,中高,高]df[分数等级]pd.cut(df[分数],binsscore_bins,labelsscore_labels)print(分数等级等宽:)print(df[[分数,分数等级]].head(10))print(\n区间分布:)print(df[分数等级].value_counts().sort_index())2.3 查看区间边界# 不指定 labels查看区间范围age_groupspd.cut(df[年龄],bins[0,30,50,100])print(年龄区间:)print(age_groups.head())# 查看区间类别print(\n区间类别:)print(age_groups.cat.categories)3. qcut() - 等频分箱qcut()根据数据的分位数进行分箱使每个箱包含大致相同数量的样本。# 等频分箱4等份df[收入等级_q]pd.qcut(df[收入],q4,labels[低,中低,中高,高])print(收入等级等频:)print(df[[收入,收入等级_q]].head())# 查看各区间样本数应该大致相等print(\n等频分箱统计:)print(df[收入等级_q].value_counts().sort_index())4. cut() vs qcut() 对比# 创建极端数据np.random.seed(42)datapd.DataFrame({值:np.random.exponential(10,100)# 指数分布数据})# 等宽分箱data[等宽]pd.cut(data[值],bins5,labels[箱1,箱2,箱3,箱4,箱5])# 等频分箱data[等频]pd.qcut(data[值],q5,labels[箱1,箱2,箱3,箱4,箱5])print(等宽 vs 等频对比:)print(等宽分箱分布:)print(data[等宽].value_counts().sort_index())print(\n等频分箱分布:)print(data[等频].value_counts().sort_index())5. 自定义分箱规则5.1 使用自定义函数defcustom_binning(x):ifx30:return青年elifx50:return中年else:return老年df[年龄段_自定义]df[年龄].apply(custom_binning)print(自定义分箱:)print(df[[年龄,年龄段_自定义]].head())5.2 使用字典映射# 先使用 cut再映射age_bins[0,30,50,100]df[年龄段代码]pd.cut(df[年龄],binsage_bins,labelsFalse)print(年龄段代码:)print(df[[年龄,年龄段代码]].head())# 代码映射为中文code_map{0:青年,1:中年,2:老年}df[年龄段_映射]df[年龄段代码].map(code_map)6. 分箱后的聚合分析# 按年龄段统计平均收入print(各年龄段平均收入:)print(df.groupby(年龄段)[收入].mean().round(0))# 按分数等级统计平均收入print(\n各分数等级平均收入:)print(df.groupby(分数等级)[收入].mean().round(0))# 多维度分组print(\n年龄段 × 分数等级 平均收入:)pivotdf.pivot_table(values收入,index年龄段,columns分数等级,aggfuncmean).round(0)print(pivot)7. 完整示例客户价值分群# 创建客户数据np.random.seed(42)customerspd.DataFrame({客户ID:[fCUST{i:04d}foriinrange(1,101)],年消费金额:np.random.exponential(5000,100).round(0),购买次数:np.random.poisson(15,100),客单价:np.random.normal(300,100,100).round(0),会员天数:np.random.randint(1,1000,100)})# 修正负值customers[客单价]customers[客单价].clip(lower0)print(*60)print(客户价值分群分析)print(*60)print(\n原始数据统计:)print(customers[[年消费金额,购买次数,客单价,会员天数]].describe())# 1. 消费金额分箱等频customers[消费等级]pd.qcut(customers[年消费金额],q4,labels[低消费,中低消费,中高消费,高消费])print(\n1. 消费等级分布:)print(customers[消费等级].value_counts())# 2. 购买频次分箱freq_bins[0,5,10,20,200]freq_labels[低频,中低频,中高频,高频]customers[频次等级]pd.cut(customers[购买次数],binsfreq_bins,labelsfreq_labels)print(\n2. 频次等级分布:)print(customers[频次等级].value_counts())# 3. 客单价分箱price_bins[0,200,300,400,1000]price_labels[低单价,中单价,高单价,超高单价]customers[单价等级]pd.cut(customers[客单价],binsprice_bins,labelsprice_labels)print(\n3. 单价等级分布:)print(customers[单价等级].value_counts())# 4. 会员时长分箱days_bins[0,30,90,180,365,1000]days_labels[新客,活跃,忠诚,资深,元老]customers[会员等级]pd.cut(customers[会员天数],binsdays_bins,labelsdays_labels)print(\n4. 会员等级分布:)print(customers[会员等级].value_counts())# 5. 客户价值评分defcalculate_score(row):# 消费金额得分0-40分amount_scoremin(row[年消费金额]/20000*40,40)# 频次得分0-30分freq_scoremin(row[购买次数]/30*30,30)# 单价得分0-20分price_scoremin(row[客单价]/500*20,20)# 忠诚度得分0-10分loyalty_scoremin(row[会员天数]/365*10,10)returnround(amount_scorefreq_scoreprice_scoreloyalty_score,2)customers[价值得分]customers.apply(calculate_score,axis1)# 6. 客户分群score_bins[0,25,50,75,100]score_labels[低价值,中低价值,中高价值,高价值]customers[客户分群]pd.cut(customers[价值得分],binsscore_bins,labelsscore_labels)print(\n5. 客户分群分布:)print(customers[客户分群].value_counts())# 7. 分群统计print(\n6. 各客户群平均指标:)segment_statscustomers.groupby(客户分群).agg({年消费金额:mean,购买次数:mean,客单价:mean,会员天数:mean,价值得分:mean}).round(2)print(segment_stats)# 8. 交叉分析print(\n7. 消费等级 × 会员等级 分布:)cross_tabpd.crosstab(customers[消费等级],customers[会员等级])print(cross_tab)8. 分箱方法对比方法特点适用场景cut()等宽区间宽度相同数据均匀分布cut()自定义边界灵活控制区间有业务含义的边界qcut()等频每箱样本数相同数据倾斜、需要平衡样本apply()自定义完全自定义复杂逻辑9. 总结函数说明示例cut(x, bins)等宽分箱pd.cut(df[age], bins[0,30,60,100])cut(x, bins, labels)带标签分箱pd.cut(df[age], bins4, labels[A,B,C,D])qcut(x, q)等频分箱pd.qcut(df[income], q4)cut(..., labelsFalse)返回区间代码pd.cut(df[age], bins3, labelsFalse)value_counts()统计分布df[bin].value_counts()
模块四-数据转换与操作——24. 数据分箱
24. 数据分箱1. 概述数据分箱Binning是将连续变量离散化的过程将数值范围划分为多个区间每个区间称为一个箱。分箱常用于将连续变量转换为分类变量便于分析和建模。importpandasaspdimportnumpyasnp# 创建示例数据np.random.seed(42)dfpd.DataFrame({姓名:[f用户_{i}foriinrange(1,21)],年龄:np.random.randint(18,70,20),收入:np.random.randint(3000,30000,20),分数:np.random.randint(0,100,20),消费次数:np.random.randint(1,100,20)})print(原始数据:)print(df.head())2. cut() - 等宽分箱2.1 基本用法cut()将数据按指定的区间边界进行分箱。# 定义年龄区间age_bins[0,30,50,100]age_labels[青年,中年,老年]df[年龄段]pd.cut(df[年龄],binsage_bins,labelsage_labels)print(年龄段分布:)print(df[[年龄,年龄段]].head())# 查看各区间计数print(\n年龄段统计:)print(df[年龄段].value_counts())2.2 自动生成区间# 指定区间数量自动等宽分箱score_bins4# 分成4等份score_labels[低,中低,中高,高]df[分数等级]pd.cut(df[分数],binsscore_bins,labelsscore_labels)print(分数等级等宽:)print(df[[分数,分数等级]].head(10))print(\n区间分布:)print(df[分数等级].value_counts().sort_index())2.3 查看区间边界# 不指定 labels查看区间范围age_groupspd.cut(df[年龄],bins[0,30,50,100])print(年龄区间:)print(age_groups.head())# 查看区间类别print(\n区间类别:)print(age_groups.cat.categories)3. qcut() - 等频分箱qcut()根据数据的分位数进行分箱使每个箱包含大致相同数量的样本。# 等频分箱4等份df[收入等级_q]pd.qcut(df[收入],q4,labels[低,中低,中高,高])print(收入等级等频:)print(df[[收入,收入等级_q]].head())# 查看各区间样本数应该大致相等print(\n等频分箱统计:)print(df[收入等级_q].value_counts().sort_index())4. cut() vs qcut() 对比# 创建极端数据np.random.seed(42)datapd.DataFrame({值:np.random.exponential(10,100)# 指数分布数据})# 等宽分箱data[等宽]pd.cut(data[值],bins5,labels[箱1,箱2,箱3,箱4,箱5])# 等频分箱data[等频]pd.qcut(data[值],q5,labels[箱1,箱2,箱3,箱4,箱5])print(等宽 vs 等频对比:)print(等宽分箱分布:)print(data[等宽].value_counts().sort_index())print(\n等频分箱分布:)print(data[等频].value_counts().sort_index())5. 自定义分箱规则5.1 使用自定义函数defcustom_binning(x):ifx30:return青年elifx50:return中年else:return老年df[年龄段_自定义]df[年龄].apply(custom_binning)print(自定义分箱:)print(df[[年龄,年龄段_自定义]].head())5.2 使用字典映射# 先使用 cut再映射age_bins[0,30,50,100]df[年龄段代码]pd.cut(df[年龄],binsage_bins,labelsFalse)print(年龄段代码:)print(df[[年龄,年龄段代码]].head())# 代码映射为中文code_map{0:青年,1:中年,2:老年}df[年龄段_映射]df[年龄段代码].map(code_map)6. 分箱后的聚合分析# 按年龄段统计平均收入print(各年龄段平均收入:)print(df.groupby(年龄段)[收入].mean().round(0))# 按分数等级统计平均收入print(\n各分数等级平均收入:)print(df.groupby(分数等级)[收入].mean().round(0))# 多维度分组print(\n年龄段 × 分数等级 平均收入:)pivotdf.pivot_table(values收入,index年龄段,columns分数等级,aggfuncmean).round(0)print(pivot)7. 完整示例客户价值分群# 创建客户数据np.random.seed(42)customerspd.DataFrame({客户ID:[fCUST{i:04d}foriinrange(1,101)],年消费金额:np.random.exponential(5000,100).round(0),购买次数:np.random.poisson(15,100),客单价:np.random.normal(300,100,100).round(0),会员天数:np.random.randint(1,1000,100)})# 修正负值customers[客单价]customers[客单价].clip(lower0)print(*60)print(客户价值分群分析)print(*60)print(\n原始数据统计:)print(customers[[年消费金额,购买次数,客单价,会员天数]].describe())# 1. 消费金额分箱等频customers[消费等级]pd.qcut(customers[年消费金额],q4,labels[低消费,中低消费,中高消费,高消费])print(\n1. 消费等级分布:)print(customers[消费等级].value_counts())# 2. 购买频次分箱freq_bins[0,5,10,20,200]freq_labels[低频,中低频,中高频,高频]customers[频次等级]pd.cut(customers[购买次数],binsfreq_bins,labelsfreq_labels)print(\n2. 频次等级分布:)print(customers[频次等级].value_counts())# 3. 客单价分箱price_bins[0,200,300,400,1000]price_labels[低单价,中单价,高单价,超高单价]customers[单价等级]pd.cut(customers[客单价],binsprice_bins,labelsprice_labels)print(\n3. 单价等级分布:)print(customers[单价等级].value_counts())# 4. 会员时长分箱days_bins[0,30,90,180,365,1000]days_labels[新客,活跃,忠诚,资深,元老]customers[会员等级]pd.cut(customers[会员天数],binsdays_bins,labelsdays_labels)print(\n4. 会员等级分布:)print(customers[会员等级].value_counts())# 5. 客户价值评分defcalculate_score(row):# 消费金额得分0-40分amount_scoremin(row[年消费金额]/20000*40,40)# 频次得分0-30分freq_scoremin(row[购买次数]/30*30,30)# 单价得分0-20分price_scoremin(row[客单价]/500*20,20)# 忠诚度得分0-10分loyalty_scoremin(row[会员天数]/365*10,10)returnround(amount_scorefreq_scoreprice_scoreloyalty_score,2)customers[价值得分]customers.apply(calculate_score,axis1)# 6. 客户分群score_bins[0,25,50,75,100]score_labels[低价值,中低价值,中高价值,高价值]customers[客户分群]pd.cut(customers[价值得分],binsscore_bins,labelsscore_labels)print(\n5. 客户分群分布:)print(customers[客户分群].value_counts())# 7. 分群统计print(\n6. 各客户群平均指标:)segment_statscustomers.groupby(客户分群).agg({年消费金额:mean,购买次数:mean,客单价:mean,会员天数:mean,价值得分:mean}).round(2)print(segment_stats)# 8. 交叉分析print(\n7. 消费等级 × 会员等级 分布:)cross_tabpd.crosstab(customers[消费等级],customers[会员等级])print(cross_tab)8. 分箱方法对比方法特点适用场景cut()等宽区间宽度相同数据均匀分布cut()自定义边界灵活控制区间有业务含义的边界qcut()等频每箱样本数相同数据倾斜、需要平衡样本apply()自定义完全自定义复杂逻辑9. 总结函数说明示例cut(x, bins)等宽分箱pd.cut(df[age], bins[0,30,60,100])cut(x, bins, labels)带标签分箱pd.cut(df[age], bins4, labels[A,B,C,D])qcut(x, q)等频分箱pd.qcut(df[income], q4)cut(..., labelsFalse)返回区间代码pd.cut(df[age], bins3, labelsFalse)value_counts()统计分布df[bin].value_counts()