You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中按组分配并复用分位数分桶?

解决方案

问题核心

原代码报错是因为不同分组的pd.qcut生成的Categorical标签(Interval类型)属于不同的分类集合,直接赋值到同一列时,Pandas要求列的Categorical类型必须一致,导致类型冲突。

方法一:统一分类类型后赋值

先收集所有分组的Interval类别,创建统一的Categorical类型,再转换每个分组的标签后赋值,同时保留分桶边界:

import numpy as np
import pandas as pd

np.random.seed(42) # 固定随机种子便于复现
df1 = pd.DataFrame({"group": "A", "val": np.random.normal(loc=10, scale=5, size=100)})
df2 = pd.DataFrame({"group": "B", "val": np.random.normal(loc=5, scale=3, size=100)})
df = pd.concat([df1, df2], ignore_index=True)

# 计算每个分组的分箱标签与边界
grouped_qcut = df.groupby("group")["val"].apply(
    lambda x: pd.qcut(x, q=5, duplicates="drop", retbins=True)
)

# 收集所有分组的Interval类别并去重排序
all_categories = []
for group in grouped_qcut.index:
    all_categories.extend(grouped_qcut[group][0].cat.categories)
all_categories = sorted(list(set(all_categories)), key=lambda x: x.left)
# 创建统一的Categorical类型
unified_cat = pd.CategoricalDtype(categories=all_categories, ordered=True)

# 保存分桶边界到字典,供后续新数据使用
bin_borders = {group: grouped_qcut[group][1] for group in grouped_qcut.index}

# 转换标签类型并赋值
for group in df["group"].unique():
    converted_labels = grouped_qcut[group][0].astype(unified_cat)
    df.loc[df["group"] == group, "value_label"] = converted_labels

方法二:使用groupby.apply统一处理(更简洁)

通过groupby.apply对每个分组添加标签,合并时Pandas会自动合并不同分组的分类集合:

import numpy as np
import pandas as pd

np.random.seed(42)
df1 = pd.DataFrame({"group": "A", "val": np.random.normal(loc=10, scale=5, size=100)})
df2 = pd.DataFrame({"group": "B", "val": np.random.normal(loc=5, scale=3, size=100)})
df = pd.concat([df1, df2], ignore_index=True)

# 用于保存各分组分桶边界的字典
bin_borders = {}

def add_qcut_label(group):
    labels, bins = pd.qcut(group["val"], q=5, duplicates="drop", retbins=True)
    bin_borders[group.name] = bins
    group["value_label"] = labels
    return group

# 应用分箱并合并结果
df = df.groupby("group", group_keys=False).apply(add_qcut_label)

后续使用分桶边界处理新数据

用保存的bin_borders字典,对新数据的对应分组执行分箱:

# 示例:处理分组A的新数据
new_data = pd.DataFrame({"group": "A", "val": np.random.normal(loc=10, scale=5, size=20)})
new_data["value_label"] = new_data.groupby("group")["val"].apply(
    lambda x: pd.cut(x, bins=bin_borders[x.name], include_lowest=True)
)

内容的提问来源于stack exchange,提问作者arabinelli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 17:42:24