为何修改列类型后调用np.select会触发布尔ndarray类型错误?
读取dirtydata.csv数据集后执行以下代码:
import pandas as pd import numpy as np df = pd.read_csv("dirtydata.csv") dfn = df.convert_dtypes() bike_sales_ds = dfn.copy() # 创建年龄区间分组列 age_conditions = [ (bike_sales_ds['Age'] <= 30), (bike_sales_ds['Age'] >= 31) & (bike_sales_ds['Age'] <= 40), (bike_sales_ds['Age'] >= 41) & (bike_sales_ds['Age'] <= 55), (bike_sales_ds['Age'] >= 56) & (bike_sales_ds['Age'] <= 69), (bike_sales_ds['Age'] >= 70) ] age_choices = ['30岁及以下', '31-40岁', '41-55岁', '56-69岁', '70岁及以上'] bike_sales_ds['Age_Range'] = np.select(age_conditions, age_choices, default='error')
触发如下错误:
Traceback (most recent call last):
File "C:\Users\dmcfa\PycharmProjects\Bike Sales Data Cleaning 01\main.py", line 43, in
bike_sales_ds['Age_Range'] = np.select(age_conditions, age_choices, default=0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<array_function internals>", line 200, in select
File "C:\Users\dmcfa\PycharmProjects\Bike Sales Data Cleaning 01\venv\Lib\site-packages\numpy\lib\function_base.py", line 845, in select
raise TypeError(
TypeError: invalid entry 0 in condlist: should be boolean ndarray
使用df.convert_dtypes(convert_integer=False)可规避错误,但无论是否调用convert_dtypes(),pd.info()均显示Age列为Int64类型,需明确错误的根本原因。
Nullable类型与NumPy的兼容性冲突
Pandas的Int64是支持空值的nullable整数类型,当你用convert_dtypes()处理后,Age列的比较结果会生成Pandas专属的BooleanArray(同样是nullable布尔类型),而非NumPy原生的bool数组。而np.select函数要求条件列表必须是标准的布尔型ndarray,无法识别Pandas的nullable布尔数组,因此抛出类型错误。pd.info()显示的误导性
原始数据集的Age列本身包含空值,Pandas读取时会自动推断为nullable的Int64类型。调用convert_dtypes()时,默认会将整数列转为Int64(和原类型一致),所以pd.info()看不出区别;但添加convert_integer=False参数后,会强制保留非nullable的原生整数类型(如int64),此时比较结果会生成NumPy原生布尔数组,就能被np.select正常处理。
除了使用convert_dtypes(convert_integer=False),还有两种更直接的处理方式:
- 将条件结果转为NumPy数组:在每个条件后追加
.values,例如(bike_sales_ds['Age'] <=30).values - 改用Pandas原生的
pd.cut函数生成年龄区间,完全避开NumPy的兼容性问题:
bike_sales_ds['Age_Range'] = pd.cut( bike_sales_ds['Age'], bins=[0, 30, 40, 55, 69, float('inf')], labels=['30岁及以下', '31-40岁', '41-55岁', '56-69岁', '70岁及以上'], include_lowest=True )
内容的提问来源于stack exchange,提问作者David M

