遍历Pandas DataFrame触发ValueError:0不在范围内的问题求助
问题分析与解决
核心问题原因
- 循环中原地删除行导致索引失效:你在循环里用
song_attributes.drop(i,inplace=True)直接删除行,这会改变DataFrame的索引集合。当后续循环再用到已经被删除的索引时,自然会触发KeyError,报错“0 is not in range”就是因为索引0已经被删掉了。 - 逻辑判断错误:第二个
if的条件mode !=1 or mode !=0永远为真——只要mode是1,那mode !=0就成立;如果mode是0,mode !=1成立。等于所有行都会被标记删除,这直接导致后续访问索引时找不到对应行。 - 链式索引的隐患:用
song_attributes['loudness'][i]这种链式索引修改值,可能会触发SettingWithCopyWarning,推荐用loc来定位修改。
修复方案1:修正循环逻辑
先收集要删除的索引,最后一次性删除,避免循环中修改DataFrame结构:
to_drop = [] # 先计算duration_ms的均值,避免循环中重复计算 duration_mean = round(song_attributes['duration_ms'].mean(), 0) for i in song_attributes.index: # 修正loudness值,用loc安全修改 if song_attributes.loc[i, 'loudness'] > 0: song_attributes.loc[i, 'loudness'] *= -1 # 修正逻辑:仅当mode既不是1也不是0时才标记删除 if song_attributes.loc[i, 'mode'] != 1 and song_attributes.loc[i, 'mode'] != 0: to_drop.append(i) # 替换过短的duration_ms if song_attributes.loc[i, 'duration_ms'] <= 1000: song_attributes.loc[i, 'duration_ms'] = duration_mean # 最后统一删除标记的行 song_attributes.drop(to_drop, inplace=True)
修复方案2:使用Pandas向量化操作(推荐)
Pandas原生支持向量化计算,效率比循环高得多,还能彻底避免索引问题:
# 处理loudness:大于0的值取反 song_attributes.loc[song_attributes['loudness'] > 0, 'loudness'] *= -1 # 过滤行:只保留mode为0或1的数据 song_attributes = song_attributes[song_attributes['mode'].isin([0, 1])] # 处理duration_ms:将<=1000的值替换为列均值 duration_mean = round(song_attributes['duration_ms'].mean(), 0) song_attributes.loc[song_attributes['duration_ms'] <= 1000, 'duration_ms'] = duration_mean
内容的提问来源于stack exchange,提问作者paul773
相关产品推荐
相关产品推荐

