使用Pandas对浮点型体重列按条件分组的问题排查
问题排查与正确实现方案
一、为什么原代码会全部标记为"0 to 20%"?
你代码里的核心错误是误用了.all()方法:
data_file['weight(kg)'].all()会返回一个布尔值(True/False),表示整个列的所有元素是否都满足前面的比较逻辑。比如data_file['weight(kg)'] <20会生成一个布尔Series,.all()会检查所有值是否都是True,最终返回单一的True或False。- Python里布尔值会被当作数字处理:True=1,False=0。你的第一个判断
0 <= data_file['weight(kg)'].all() <20其实是在判断0 <= 1 <20(因为你的数据里不是所有体重都<20,.all()返回False?不对,哦不,你写的data_file['weight(kg)'].all()是直接对列的所有元素判断是否为“真”(非零),你的体重都是正数,所以.all()返回True,也就是1,自然满足0<=1<20,所以第一个if执行,给整个target列赋值为"0 to 20%"。 - 后面的
if条件里,data_file['weight(kg)'].all()同样返回True,但20 <1 <40不成立,所以后续赋值都不会执行,最终所有行的Target都是第一个if设置的值。
二、正确的实现方式
针对这种区间分组需求,推荐两种高效的方法:
方法1:用pd.cut()(pandas原生区间分组工具,简洁高效)
pd.cut()专门用于将连续数值分组到离散区间,完美匹配你的场景:
import pandas as pd # 构造数据集(已有数据框可跳过此步) data = { 'Name': [f'Person{i}' for i in range(1,11)], 'weight(kg)': [4.44, 37.3, 36.38, 39.52, 81.57, 43.55, 91.11, 5, 36.48, 38.25] } data_file = pd.DataFrame(data) # 定义区间边界和对应标签 bins = [0, 20, 40, 60, 80, 100] labels = ["0 to 20", "20 to 40", "40 to 60", "60 to 80", "80 to 100"] # 生成Target列:include_lowest确保第一个区间包含0,right=False设置左闭右开匹配你的规则 data_file['Target'] = pd.cut( data_file['weight(kg)'], bins=bins, labels=labels, include_lowest=True, right=False ) # 查看结果 print(data_file)
方法2:用np.select()(灵活处理自定义条件)
如果你需要更精细控制区间的开闭规则(比如你的区间是混合左开右闭/左闭右开的情况),可以用np.select()逐行判断:
import pandas as pd import numpy as np # 构造数据集 data = { 'Name': [f'Person{i}' for i in range(1,11)], 'weight(kg)': [4.44, 37.3, 36.38, 39.52, 81.57, 43.55, 91.11, 5, 36.48, 38.25] } data_file = pd.DataFrame(data) # 定义每个区间的判断条件 conditions = [ (data_file['weight(kg)'] >= 0) & (data_file['weight(kg)'] < 20), (data_file['weight(kg)'] > 20) & (data_file['weight(kg)'] < 40), (data_file['weight(kg)'] > 40) & (data_file['weight(kg)'] < 60), (data_file['weight(kg)'] > 60) & (data_file['weight(kg)'] < 80), (data_file['weight(kg)'] > 80) & (data_file['weight(kg)'] <= 100) ] # 对应每个条件的标签 choices = [ "0 to 20", "20 to 40", "40 to 60", "60 to 80", "80 to 100" ] # 生成Target列,default处理不满足任何条件的情况(比如体重<0或>100) data_file['Target'] = np.select(conditions, choices, default=np.nan) # 查看结果 print(data_file)
三、最终验证结果
两种方法都会生成你期望的输出:
Name weight(kg) Target 0 Person1 4.44 0 to 20 1 Person2 37.30 20 to 40 2 Person3 36.38 20 to 40 3 Person4 39.52 20 to 40 4 Person5 81.57 80 to 100 5 Person6 43.55 40 to 60 6 Person7 91.11 80 to 100 7 Person8 5.00 0 to 20 8 Person9 36.48 20 to 40 9 Person10 38.25 20 to 40
内容的提问来源于stack exchange,提问作者sre
相关产品推荐
相关产品推荐

