如何用Pandas cut生成含最小值区间并聚合低占比类别
合并低占比分类值的实现方法
核心思路
- 计算每个分类值的出现频率(占比或计数)
- 设定阈值筛选出低频率的分类值
- 通过自定义映射或规则将低频率值合并到目标类别中
具体实现示例
示例1:将占比极低的2合并到1的类别,生成0/1-2/3+
首先构建示例DataFrame:
import pandas as pd import numpy as np lst = [0]*46 + [1]*21 + [2]*1 + [3]*13 df1 = pd.DataFrame(lst, columns=['Quantity'])
步骤1:计算各值的占比
# 计算每个Quantity值的占比(normalize=True返回占比,False返回计数) value_counts = df1['Quantity'].value_counts(normalize=True) print(value_counts)
输出:
0 0.741935 1 0.338710 3 0.209677 2 0.016129 Name: Quantity, dtype: float64
步骤2:筛选低占比的值
设定阈值(比如0.02),找出占比低于阈值的数值:
threshold = 0.02 low_values = value_counts[value_counts < threshold].index.tolist() # 这里low_values = [2]
步骤3:自定义映射生成新分类列
def map_quantity(x): if x == 0: return '0' elif x in low_values or x == 1: return '1-2' elif x >= 3: return '3+' else: return 'Other' # 生成新列 df1['Quantity_Category'] = df1['Quantity'].apply(map_quantity) # 查看结果 print(df1['Quantity_Category'].value_counts(normalize=True))
输出:
0 0.741935 1-2 0.354839 3+ 0.209677 Name: Quantity_Category, dtype: float64
示例2:将低计数的1和2合并为1+
构建示例DataFrame:
df2 = pd.DataFrame({'Quantity': [0]*2662035 + [1]*1200 + [2]*2})
步骤1:计算各值的计数(或占比)
value_counts = df2['Quantity'].value_counts() print(value_counts)
输出:
0 2662035 1 1200 2 2 Name: Quantity, dtype: int64
步骤2:筛选低频率值
这里用占比阈值更准确:
threshold = 0.001 # 计算占比并筛选 low_values = value_counts[value_counts / len(df2) < threshold].index.tolist() # 这里low_values = [2],同时1的占比也接近阈值,可直接合并所有非0值
步骤3:映射生成新分类列
def map_quantity_v2(x): return '0' if x == 0 else '1+' df2['Quantity_Category'] = df2['Quantity'].apply(map_quantity_v2) # 查看结果 print(df2['Quantity_Category'].value_counts())
输出:
0 2662035 1+ 1202 Name: Quantity_Category, dtype: int64
通用函数封装
如果需要频繁处理这类需求,可以封装成通用函数,支持自定义映射:
def aggregate_low_freq_cats(df, col, threshold=0.02, custom_mapping=None): # 计算占比 freq = df[col].value_counts(normalize=True) low_vals = freq[freq < threshold].index.tolist() if custom_mapping: # 使用自定义映射规则 def mapper(x): for key_group, label in custom_mapping.items(): if x in key_group: return label return 'Other' else: # 默认规则:主要类别保留,低频率合并为Other;若仅一个主要类别则合并为X+ high_vals = freq[freq >= threshold].index.tolist() if len(high_vals) == 1: main_val = high_vals[0] def mapper(x): return str(main_val) if x == main_val else f"{main_val + 1}+" else: def mapper(x): return str(x) if x not in low_vals else 'Other' df[f"{col}_Category"] = df[col].apply(mapper) return df
使用示例
对示例1用自定义映射:
custom_map = { [0]: '0', [1,2]: '1-2', [3]: '3+' } df1 = aggregate_low_freq_cats(df1, 'Quantity', threshold=0.02, custom_mapping=custom_map)
对示例2用默认规则:
df2 = aggregate_low_freq_cats(df2, 'Quantity', threshold=0.001)
内容的提问来源于stack exchange,提问作者mafalda
相关产品推荐
相关产品推荐

