Pandas批量匹配数值对应的区间上下限问题(bisect报错求助)
Pandas批量匹配数值对应的区间上下限问题(bisect报错求助)
嘿,我懂你现在的困扰!你用bisect报错是因为bisect_left/bisect_right只能处理单个数值,没法直接接收Pandas Series这种数组类型的输入——当你把整列Series传进去时,函数会试图判断整个Series的“真值”,这在Pandas里是不允许的,所以才会抛出那个模糊真值的错误。而且你的数据集有60万行,循环处理肯定慢到离谱,得用矢量化的方法来解决。
给你两个高效的解决方案,都是专门对付这种批量区间匹配场景的:
方法一:用Pandas自带的pd.cut(最直观)
pd.cut是Pandas专门为分箱设计的函数,完美契合你的需求,代码也很易懂:
import pandas as pd import numpy as np bin_limits = [0,25000,50000,75000,100000,150000,250000,500000,1000000] df = pd.DataFrame({'number': [12500,50123,165687,500001,150000,1000000],}) # 第一步:给number列分箱,include_lowest确保最小的区间包含0 df['bin_interval'] = pd.cut(df['number'], bins=bin_limits, include_lowest=True) # 第二步:从区间对象里提取上下限 df['lower_bin'] = df['bin_interval'].apply(lambda x: x.left) df['upper_bin'] = df['bin_interval'].apply(lambda x: x.right) # 不需要中间列的话可以删掉 df = df.drop('bin_interval', axis=1)
运行后你就能得到想要的结果:
| number | lower_bin | upper_bin |
|---|---|---|
| 12500 | 0 | 25000 |
| 50123 | 50000 | 75000 |
| 165687 | 150000 | 250000 |
| 500001 | 500000 | 1000000 |
| 150000 | 100000 | 150000 |
| 1000000 | 500000 | 1000000 |
方法二:用Numpy的digitize(速度更快)
如果你追求极致性能,Numpy的digitize是更好的选择,它的底层是C实现,处理60万行数据毫无压力:
import pandas as pd import numpy as np bin_limits = [0,25000,50000,75000,100000,150000,250000,500000,1000000] df = pd.DataFrame({'number': [12500,50123,165687,500001,150000,1000000],}) # 获取每个数值对应的区间索引(和bisect_right行为一致) indices = np.digitize(df['number'], bin_limits, right=True) # 通过索引提取上下限 df['lower_bin'] = np.array(bin_limits)[indices - 1] df['upper_bin'] = np.array(bin_limits)[indices]
这个方法的结果和上面完全一样,但速度会比pd.cut快一些,适合超大规模数据集。
为啥你的原代码会报错?
再啰嗦两句:bisect系列函数是给单个数值做二分查找用的,比如你给它一个单独的12500,它能返回正确的索引,但你直接塞一整列Series,函数不知道该怎么处理整个数组的判断逻辑,就会抛出那个“真值模糊”的错误——这也是Pandas新手常踩的坑哦。
备注:内容来源于stack exchange,提问作者Nick_FN
相关产品推荐
相关产品推荐

