pandas使用iloc配合idxmax取值时触发IndexError位置索引越界问题
报错根因
核心是混淆了pandas的两套独立索引逻辑,和copy、deepcopy的拷贝方式完全无关:
Series.idxmax()方法返回的是列最大值对应的行索引标签值,也就是DataFrame的index属性存储的标识值,不是行在表内的整数排列位置iloc[]是纯整数位置索引器,只接受从0开始、按行排序的连续位置序号,完全不识别索引标签本身的数值- 原始大表
f2021能正常运行,是因为它的行索引是默认生成的连续0~N整数标签,此时索引标签的数值和行的实际位置完全相等,把idxmax()返回的标签值传给iloc时刚好能匹配位置,不会触发越界 - 子集
f2021_1必现越界的原因:作为从大表筛选生成的子集,只要没有主动重置索引,它的行索引会完全继承原大表的非连续标签值。比如原大表共10万行,筛选后仅剩500行,保留的索引标签可能是[1023, 4567, 98001]这类远大于子集总行数的数值。此时idxmax()返回的标签值(比如98001)被传入iloc后,位置索引器会尝试找第98001行位置,但子集本身仅500行,自然触发IndexError越界。
补充:不管是普通copy还是deepcopy,都只会复制数据本身的内容,不会修改子集继承来的非连续索引标签,所以两种拷贝方式都无法解决这个问题。
修正方案
- 优先采用索引匹配的写法:把报错语句里的位置索引器替换为标签索引器
loc,和idxmax()返回的标签值完全适配,不需要修改原有子集的生成逻辑:date.append(f2021_1.loc[f2021_1[j].idxmax(), 'ts']) - 备选方案:生成
f2021_1时主动重置索引,让子集的索引变回连续的0~N整数标签:
这种写法下原代码可以正常运行,但如果后续依然混淆标签索引和位置索引,还是会出现同类问题。# 生成子集的代码后追加重置索引操作 f2021_1 = f2021[筛选条件].reset_index(drop=True)
内容的提问来源于stack exchange,提问作者Miss.Pepper
相关产品推荐
相关产品推荐

