Python中Pandas Dataframe的out of bounds问题如何解决

假设原有的每个独立 csv 是 9 个 column,后期的每个独立 csv 增加了一列,即 10 个 column

通过 pandas 读取所有新老 csv df = pd.DataFrame(pd.read_csv(file))

希望取到第 10 个 column 的数值,如果是老的 csv,该增加列可以取空值。

在利用 df.iloc 取值时,对于老的 csv,会报 out of bounds 错误 老的 csv 文件也有数千个

求教有好的解决方案吗?


Python中Pandas Dataframe的out of bounds问题如何解决

3 回复

遇到 out of bounds 错误,通常是尝试用整数索引访问了不存在的行或列。在Pandas里,这多半是索引越界了。我直接给你看几个常见情况和对应的代码。

情况1:用.iloc按整数位置索引时越界 .iloc是基于0的整数位置索引。如果你的DataFrame只有5行,你尝试取.iloc[5]就会报IndexError: single positional indexer is out-of-bounds

import pandas as pd

df = pd.DataFrame({'A': [1, 2, 3, 4, 5]})
print(df)
#     A
# 0  1
# 1  2
# 2  3
# 3  4
# 4  5

# 错误示例:索引5不存在(有效索引是0-4)
try:
    value = df.iloc[5]
except IndexError as e:
    print(f"错误:{e}")

# 正确做法:先检查长度
if 5 < len(df):
    value = df.iloc[5]
else:
    print(f"索引5超出范围,DataFrame长度为{len(df)}")
    # 或者取最后一个
    value = df.iloc[-1]
    print(f"改为取最后一个元素:{value}")

情况2:用.loc按标签索引时,标签不存在 .loc是按索引标签查找。如果你的索引是默认的整数范围,但标签不存在,也会报错。

# 假设我们有一个非连续索引的DataFrame
df2 = pd.DataFrame({'A': [10, 20, 30]}, index=[5, 10, 15])
print(df2)
#     A
# 5   10
# 10  20
# 15  30

# 错误示例:尝试访问不存在的标签
try:
    value = df2.loc[7]
except KeyError as e:
    print(f"错误:{e}")

# 正确做法:使用`in`检查标签是否存在,或者用`.get()`
if 7 in df2.index:
    value = df2.loc[7]
else:
    print("标签7不存在于索引中。")
    # 或者使用reindex或fillna来处理缺失
    value = df2.reindex([7, 5, 10]) # 重新索引,不存在的标签会产生NaN
    print(f"重新索引后的结果:\n{value}")

情况3:在循环或动态计算索引时越界 这在处理数据时很常见,比如根据前一行的值计算下一行。

# 一个容易出错的循环示例
data = []
for i in range(len(df)):
    # 错误:当i是最后一行时,i+1越界
    # next_val = df.iloc[i+1]['A']  # 这会报错
    pass

# 更安全的做法:使用`shift`或确保索引有效
df['A_shifted'] = df['A'].shift(-1)  # 将下一行的值移到当前行,最后一行会是NaN
print(df)
#     A  A_shifted
# 0  1        2.0
# 1  2        3.0
# 2  3        4.0
# 3  4        5.0
# 4  5        NaN

# 或者在循环中明确限制范围
for i in range(len(df) - 1): # 注意范围是 len(df)-1
    current_val = df.iloc[i]['A']
    next_val = df.iloc[i+1]['A']
    print(f"行{i}: {current_val}, 下一行: {next_val}")

通用调试和解决方法:

  1. 打印形状和索引:在关键操作前,用 print(df.shape)print(df.index) 看看你到底在操作什么。
  2. 使用.iloc.loc时要清醒:记住 .iloc 用的是整数位置(0到len-1),.loc 用的是索引标签。别搞混了。
  3. 考虑使用.at.iat获取标量:如果只是取一个确定存在的单元格,它们更快。
  4. try-except包裹可能出错的操作:这是最直接的防御性编程。
  5. 检查索引重置:如果你刚做过筛选或合并,索引可能不连续了。用 df.reset_index(drop=True, inplace=True) 重置为连续的整数索引,能避免很多意外。

总结:核心就是搞清楚你用的是位置索引还是标签索引,并确保它们存在。


用 get(),如果列有名字则用名字,否则用序号,get 如果没有则返回 None,方便处理。

In [2]: import pandas as pd

In [3]: df = pd.DataFrame(np.random.randn(8, 4))

In [4]: df
Out[4]:
0 1 2 3
0 -0.727670 -0.182557 -0.957270 -0.153352
1 -0.340649 -0.313155 -1.219515 0.082472
2 0.023527 0.496896 0.443117 -0.391405
3 -0.522745 0.879736 -1.358356 0.177883
4 -0.314936 -1.795936 -1.510872 1.039757
5 0.000243 -0.826999 -0.365514 -0.907249
6 0.058694 -0.521912 -0.863121 0.842308
7 0.846951 0.325337 -0.821745 0.111492

In [5]: df.get(0)
Out[5]:
0 -0.727670
1 -0.340649
2 0.023527
3 -0.522745
4 -0.314936
5 0.000243
6 0.058694
7 0.846951
Name: 0, dtype: float64

In [6]: df.get(1)
Out[6]:
0 -0.182557
1 -0.313155
2 0.496896
3 0.879736
4 -1.795936
5 -0.826999
6 -0.521912
7 0.325337
Name: 1, dtype: float64

In [7]: df.get(3)
Out[7]:
0 -0.153352
1 0.082472
2 -0.391405
3 0.177883
4 1.039757
5 -0.907249
6 0.842308
7 0.111492
Name: 3, dtype: float64

In [8]: df.get(4)

In [9]:

或者列有名字:

In [10]: df = pd.DataFrame(np.random.randn(8, 4), columns=[‘A’, ‘B’, ‘C’, ‘D’])

In [11]: df
Out[11]:
A B C D
0 -1.521750 -0.704144 -0.565343 -0.389537
1 -0.634391 0.672338 0.857965 0.294724
2 -0.764034 0.907585 -1.454368 -0.637835
3 -1.218633 -1.473434 1.441891 1.554465
4 -1.100643 -2.303968 -1.788275 -0.382192
5 1.476041 -0.735864 -0.359389 0.896467
6 1.662332 -0.944238 0.308855 -0.013283
7 1.357332 0.529256 1.169877 0.745932

In [12]: df.get(‘E’)

In [13]: df.get(‘B’)
Out[13]:
0 -0.704144
1 0.672338
2 0.907585
3 -1.473434
4 -2.303968
5 -0.735864
6 -0.944238
7 0.529256
Name: B, dtype: float64

实在不行还可以用 try except 吧。

楼上的方法 get 是不错的方法,还有就是可以判断 dataframe 的 shape 大小,针对列大小不一致的情况你处理下就好了

回到顶部