pandas使用loc按条件筛选行选列时触发KeyError的解决方法

问题说明
- 需求:获取数据集第13列至第21列的全部数据,筛选第1列
is_canceled取值为1的行,将两类数据做对比 - 已排查项:字段名前后空格问题,排查后仍触发报错
出错代码
hotel_bookings.loc[hotel_bookings.is_canceled==1,hotel_bookings.country]
报错信息
KeyError Traceback (most recent call last) <ipython-input-148-91ca78d709e4> in <module>() ----> 1 hotel_bookings.loc[hotel_bookings.is_canceled==1,hotel_bookings.country] 6 frames /usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py in _validate_read_indexer(self, key, indexer, axis) 1372 if use_interval_msg: 1373 key = list(key) -> 1374 raise KeyError(f"None of [{key}] are in the [{axis_name}]") 1375 1376 not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique()) KeyError: "None of [Index(['PRT', 'PRT', 'GBR', 'GBR', 'GBR', 'GBR', 'PRT', 'PRT', 'PRT', 'PRT',\n ...\n 'DEU', 'DEU', 'JPN', 'DEU', 'BEL', 'BEL', 'FRA', 'DEU', 'GBR', 'DEU'],\n dtype='object', length=119390)] are in the [columns]"
报错原因
核心是loc的列筛选参数传错:loc的语法规则是数据集.loc[行筛选逻辑, 列筛选范围],第二个位置的参数只能传列名、列名列表,或者和列数等长的布尔序列。你传入的hotel_bookings.country是country列存储的所有具体值(也就是报错里打印的PRT、GBR这类国家编码,总长度119390和数据集总行数一致),pandas会把这一长串值当成你要查找的列名,自然匹配不到任何列,直接抛出KeyError。
另外你写的代码和实际需求不匹配:目标是取第13到21列,代码里却只写了country单列,完全没有覆盖目标列范围。
修正方案
pandas默认索引从0开始计数,按日常从1开始数列的习惯,第13到21列对应索引位置是12到20,利用iloc先取目标列名,再传给loc做筛选即可,同时可以直接取出未取消订单的同范围数据做对比:
# 提取第13列到第21列的列名(iloc切片左闭右开,所以结束位置写21刚好覆盖到第21列) target_columns = hotel_bookings.iloc[:, 12:21].columns # 筛选已取消订单的目标列数据 canceled_df = hotel_bookings.loc[hotel_bookings["is_canceled"] == 1, target_columns] # 筛选未取消订单的目标列数据,用于对比 not_canceled_df = hotel_bookings.loc[hotel_bookings["is_canceled"] == 0, target_columns]
提示:如果你是从0开始计数列序号,对应调整iloc的切片起止位置即可
内容的提问来源于stack exchange,提问作者Alice T
相关产品推荐
相关产品推荐

