如何在Python中基于动态区间对数据进行分箱统计?
基于value_counts()实现动态分箱的统计方案
先构造示例数据
假设你的DataFrame结构如下(可根据实际情况调整):
import pandas as pd # df1:存储各ID对应的动态分箱区间(注意将区间整理为连续的bins数组,比如[100,150,170]对应两个区间[100,150)、[150,170]) df1 = pd.DataFrame({ 'ID': ['ID_1', 'ID_2'], 'bins': [[100, 150, 170], [80, 105, 120]] }) # df2:存储各ID的数值数据 df2 = pd.DataFrame({ 'ID': ['ID_1']*10 + ['ID_2']*10, 'value': [120, 140, 160, 110, 150, 170, 130, 165, 100, 150] + [90, 100, 105, 110, 80, 120, 95, 105, 115, 85] })
核心实现代码
利用groupby+apply结合value_counts(),可以简洁完成动态分箱的统计:
def process_id_group(group): # 获取当前ID对应的分箱规则 target_bins = df1.loc[df1['ID'] == group.name, 'bins'].iloc[0] # 对当前分组的数值进行分箱,include_lowest=True确保左区间最小值被包含 group['bin_interval'] = pd.cut(group['value'], bins=target_bins, include_lowest=True) # 用value_counts()统计各区间数量 bin_stats = group['bin_interval'].value_counts().reset_index(name='count') # 计算占比:当前区间数量/该ID总数据量 total_samples = group.shape[0] bin_stats['proportion'] = bin_stats['count'] / total_samples # 补充ID列 bin_stats['ID'] = group.name # 调整列顺序 return bin_stats[['ID', 'bin_interval', 'count', 'proportion']] # 按ID分组处理,合并结果得到df3 df3 = df2.groupby('ID').apply(process_id_group).reset_index(drop=True)
结果说明
运行后df3为长表格式(适合后续分析),示例输出如下:
| ID | bin_interval | count | proportion |
|---|---|---|---|
| ID_1 | (149.999, 170] | 4 | 0.4 |
| ID_1 | [100.0, 150.0) | 6 | 0.6 |
| ID_2 | (105.0, 120] | 3 | 0.3 |
| ID_2 | [80.0, 105.0) | 7 | 0.7 |
可选:转换为宽表格式
如果需要将分箱区间作为单独列(方便报表展示),可以用pivot转换:
df3_wide = df3.pivot( index='ID', columns='bin_interval', values=['count', 'proportion'] ).reset_index() # 重命名列,提升可读性 df3_wide.columns = ['ID'] + [f'{interval}_{stat_type}' for stat_type, interval in df3_wide.columns[1:]]
注意事项
- 确保df1中的分箱区间连续且无重叠,否则
pd.cut会生成NaN,可通过添加dropna=False保留这些记录。 - 若分箱是左开右闭规则,可设置
pd.cut(right=False)来匹配区间逻辑。 - 该方案支持任意数量的ID和分箱区间,完全适配动态场景。
内容的提问来源于stack exchange,提问作者LostinSpatialAnalysis
相关产品推荐
相关产品推荐

