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

Python 3.10创建DataFrame分桶遇TypeError:无法设置Categorical新类别

问题:分桶AGE变量后执行ANOVA分析时触发Categorical类型错误

我有一个包含AGE和MEDV数值列的DataFrame,想把AGE分成3个分桶后做ANOVA分析,但执行代码时第一行就报错:

TypeError: Cannot setitem on a Categorical with a new category (Less than 35), set the categories first

尝试的代码如下:

df.loc[(df['AGE'] <= 35), 'age_group'] = 'Less than 35'
df.loc[(df['AGE'] > 35)&(df["AGE"] < 70), 'age_group'] = '35 to 70'
df.loc[(df['AGE'] > 70), 'age_group'] = 'Over 70'

# Separate samples into a variable each
a = df[df['age_group'] == "Less than 35"]["MEDV"]
b = df[df['age_group'] == "35 to 70"]["MEDV"]
c = df[df['age_group'] == "Over 70"]["MEDV"]

f_statistic, p_value = stats.f_oneway(a, b, c)
print("F_Statistic: {0}, P-Value: {1}".format(f_statistic,p_value))

使用Python 3.10的Jupyter Notebook,之前在其他环境用过类似代码正常运行,疑惑是遗漏步骤还是版本变更导致?


报错原因

这个错误和Python 3.10版本无关,核心问题是你要赋值的age_group列已经被定义为Categorical类型了。Categorical列的特点是只能使用预先定义好的类别值,直接赋值新的类别会触发这个错误。之前其他环境能运行,大概率是当时的age_group列是默认的object(字符串)类型,没有Categorical的限制。


解决方法

方法1:先初始化普通字符串列再赋值

先创建一个空的字符串列,避免Categorical的限制,赋值完成后可按需转为Categorical类型:

# 先创建普通字符串列
df['age_group'] = ''
# 执行分桶赋值
df.loc[(df['AGE'] <= 35), 'age_group'] = 'Less than 35'
df.loc[(df['AGE'] > 35)&(df["AGE"] < 70), 'age_group'] = '35 to 70'
df.loc[(df['AGE'] > 70), 'age_group'] = 'Over 70'

# 可选:转为有序Categorical类型,方便后续分析
df['age_group'] = pd.Categorical(df['age_group'], categories=['Less than 35', '35 to 70', 'Over 70'], ordered=True)

方法2:预先定义Categorical列的所有类别

如果需要一开始就用Categorical类型,先提前声明所有允许的类别:

# 先创建Categorical列并指定所有类别
df['age_group'] = pd.Categorical([], categories=['Less than 35', '35 to 70', 'Over 70'], ordered=True)
# 再执行赋值
df.loc[(df['AGE'] <= 35), 'age_group'] = 'Less than 35'
df.loc[(df['AGE'] > 35)&(df["AGE"] < 70), 'age_group'] = '35 to 70'
df.loc[(df['AGE'] > 70), 'age_group'] = 'Over 70'

方法3:用pd.cut直接生成分桶列(推荐)

用pandas内置的pd.cut函数可以一步完成分桶,自动处理类别,避免手动赋值的麻烦:

import pandas as pd
from scipy import stats

# 定义分桶边界和标签
bins = [0, 35, 70, float('inf')]
labels = ['Less than 35', '35 to 70', 'Over 70']
# 生成分桶列
df['age_group'] = pd.cut(df['AGE'], bins=bins, labels=labels, include_lowest=True)

# 后续ANOVA代码不变
a = df[df['age_group'] == "Less than 35"]["MEDV"]
b = df[df['age_group'] == "35 to 70"]["MEDV"]
c = df[df['age_group'] == "Over 70"]["MEDV"]

f_statistic, p_value = stats.f_oneway(a, b, c)
print("F_Statistic: {0}, P-Value: {1}".format(f_statistic,p_value))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:57:04