You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复Python 3D散点图绘制中的KeyError索引错误

问题排查与修复

问题描述

使用pandas读取CSV文件,结合matplotlib绘制3D散点图时,全量数据绘图正常,但绘制误差点时触发KeyError。需求是绘制t3/e1/e2范围内的Z值误差点,通过Zup=ZMax-Z、Zlow=Z-ZMin定位目标点,怀疑是CSV格式或代码逻辑问题。

错误信息

runfile('C:/Users/GregL/.matplotlib/test of loops.py', wdir='C:/Users/GregL/.matplotlib')
c:\users\gregl\.matplotlib\test of loops.py:19: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.z = mergeddata['central distance']
c:\users\gregl\.matplotlib\test of loops.py:20: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.x = mergeddata['x par']
c:\users\gregl\.matplotlib\test of loops.py:21: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.y = mergeddata['y rad']
c:\users\gregl\.matplotlib\test of loops.py:22: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.ZMax = mergeddata ['Z Max']
c:\users\gregl\.matplotlib\test of loops.py:23: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.ZMin = mergeddata ['Z Min']
c:\users\gregl\.matplotlib\test of loops.py:24: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.Zup = mergeddata ['Upper Lim']
c:\users\gregl\.matplotlib\test of loops.py:25: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  mergeddata.Zlow = mergeddata ['Lower Lim']
Traceback (most recent call last):

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\spyder_kernels\py3compat.py", line 356, in compat_exec
    exec(code, globals, locals)

  File "c:\users\gregl\.matplotlib\test of loops.py", line 53, in <module>
    surf=ax.scatter3D(x[z1],y[z1],z[z1],c='red',cmap=plt.cm.coolwarm,s=.1,marker='x')

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\series.py", line 984, in __getitem__
    return self._get_with(key)

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\series.py", line 1024, in _get_with
    return self.loc[key]

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\indexing.py", line 967, in __getitem__
    return self._getitem_axis(maybe_callable, axis=axis)

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\indexing.py", line 1191, in _getitem_axis
    return self._getitem_iterable(key, axis=axis)

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\indexing.py", line 1132, in _getitem_iterable
    keyarr, indexer = self._get_listlike_indexer(key, axis)

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\indexing.py", line 1327, in _get_listlike_indexer
    keyarr, indexer = ax._get_indexer_strict(key, axis_name)

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\indexes\base.py", line 5782, in _get_indexer_strict
    self._raise_if_missing(keyarr, indexer, axis_name)

  File "C:\Users\GregL\AppData\Local\Programs\Spyder\pkgs\pandas\core\indexes\base.py", line 5842, in _raise_if_missing
    raise KeyError(f"None of [{key}] are in the [{axis_name}]")

KeyError: "None of [Float64Index([      2313.3108334,     57.91915734032,      70.6299190667,\n                    120.02294505,      124.254986712, 243.31550280000002,\n              243.31550280000002,      146.105908289,      146.105908289,\n                   141.393578059,\n              ...\n                     383118.4458,        406598.8082,        466337.6262,\n                     485021.8653,        676614.4588,        816073.0216,\n                      1032968.11,        3354015.867,        7916505.371,\n                     7953742.675],\n             dtype='float64', length=8544)] are in the [index]"

原代码

from mpl_toolkits import mplot3d
import matplotlib.colors as col
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd

headers = ['name','ra','x rads','x par','dec','y rad','Parallax','Parallax Error','central distance','Z Max','Upper Lim','Z Min','Lower Lim']
mergeddata = pd.read_csv(r'C:\Users\GregL\Downloads\mergedata - no neg parallax #s (3).csv')

mergeddata.z = mergeddata['central distance']
mergeddata.x = mergeddata['x par']
mergeddata.y = mergeddata['y rad']
mergeddata.ZMax = mergeddata ['Z Max']
mergeddata.ZMin = mergeddata ['Z Min']
mergeddata.Zup = mergeddata ['Upper Lim']
mergeddata.Zlow = mergeddata ['Lower Lim']

x = mergeddata.x
y = mergeddata.y
z = mergeddata.z
ZMax = mergeddata.ZMax
ZMin = mergeddata.ZMin
Zup = mergeddata.Zup
Zlow = mergeddata.Zlow

t3 = (z >= 1695.477401) & (z <= 2313.310833)

e1 = (z <= 1695.477401) & (z <= 2313.310833) & (ZMax >= 1695.477301) & (ZMax <= (1.5*2313.310833)) 

e2 = (z <=1695.477401) & (z <= 2313.310833) & (ZMin >= (1.5*1695.477401)) & (ZMin <=2313.310833)

for z1 in e1:
    z1 = z + Zup
    
for z2 in e2:
    z2 = z - Zlow
    

fig = plt.figure(figsize=(10,10))

ax = fig.add_subplot(111,projection ='3d')

surf=ax.scatter3D(x[t3],y[t3],z[t3],c='green',cmap=plt.cm.coolwarm,s=.5,marker='^')
surf=ax.scatter3D(x[z1],y[z1],z[z1],c='red',cmap=plt.cm.coolwarm,s=.1,marker='x')
surf=ax.scatter3D(x[z2],y[z2],z[z2],c='blue',cmap=plt.cm.coolwarm,s=.1,marker='-')

ax.set_title('3D Data Distance Plot')

ax.set_zlim(-100,10000)
ax.set_xlim(-50,50)
ax.set_ylim(-50,50)

ax.set_xlabel('RA')
ax.set_ylabel('DEC')
ax.set_zlabel('CENTRAL DISTANCE')

plt.show()

问题根源与修复方案

1. DataFrame列赋值警告

pandas不允许通过属性方式(mergeddata.z)创建新列,必须使用字典索引语法(mergeddata['z']),否则会触发警告且可能导致后续逻辑异常。

2. 布尔索引与误差点计算逻辑错误

原代码中的for循环完全错误:

  • e1、e2是布尔数组(掩码),用于筛选符合条件的行,而非可迭代的数值列表
  • 误差点的Z坐标应该是筛选后的数据行对应的z + Zup和z - Zlow,而非对全量数据进行计算

3. 索引错误

原代码用z1(数值数组)去索引x/y/z,这相当于用数值作为行索引查找,而DataFrame的行索引是整数,导致KeyError。正确做法是用布尔掩码e1/e2筛选数据,再计算对应的误差Z值。

4. 条件逻辑冗余

e1中的z <=1695.477401 & z <=2313.310833重复,可简化为z <=1695.477401;同理e2的条件也可简化。

修正后的完整代码

from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 读取CSV文件,指定表头(如果CSV文件本身没有表头的话)
headers = ['name','ra','x rads','x par','dec','y rad','Parallax','Parallax Error','central distance','Z Max','Upper Lim','Z Min','Lower Lim']
mergeddata = pd.read_csv(r'C:\Users\GregL\Downloads\mergedata - no neg parallax #s (3).csv', names=headers)

# 用字典索引创建新列,修复警告
mergeddata['z'] = mergeddata['central distance']
mergeddata['x'] = mergeddata['x par']
mergeddata['y'] = mergeddata['y rad']
mergeddata['ZMax'] = mergeddata['Z Max']
mergeddata['ZMin'] = mergeddata['Z Min']
mergeddata['Zup'] = mergeddata['Upper Lim']
mergeddata['Zlow'] = mergeddata['Lower Lim']

# 提取所需列
x = mergeddata['x']
y = mergeddata['y']
z = mergeddata['z']
ZMax = mergeddata['ZMax']
ZMin = mergeddata['ZMin']
Zup = mergeddata['Zup']
Zlow = mergeddata['Zlow']

# 定义筛选条件,简化冗余逻辑
t3_mask = (z >= 1695.477401) & (z <= 2313.310833)
e1_mask = (z <= 1695.477401) & (ZMax >= 1695.477301) & (ZMax <= 1.5 * 2313.310833)
e2_mask = (z <= 1695.477401) & (ZMin >= 1.5 * 1695.477401) & (ZMin <= 2313.310833)

# 计算误差点的Z坐标:仅对符合条件的行计算
z_e1 = z[e1_mask] + Zup[e1_mask]
z_e2 = z[e2_mask] - Zlow[e2_mask]

# 绘制3D散点图
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111, projection='3d')

# 绘制t3范围内的点
ax.scatter3D(x[t3_mask], y[t3_mask], z[t3_mask], c='green', s=.5, marker='^')
# 绘制e1误差点
ax.scatter3D(x[e1_mask], y[e1_mask], z_e1, c='red', s=.1, marker='x')
# 绘制e2误差点:将'-'改为'o',因为'-'不是有效的3D散点标记
ax.scatter3D(x[e2_mask], y[e2_mask], z_e2, c='blue', s=.1, marker='o')

ax.set_title('3D Data Distance Plot')
ax.set_zlim(-100, 10000)
ax.set_xlim(-50, 50)
ax.set_ylim(-50, 50)

ax.set_xlabel('RA')
ax.set_ylabel('DEC')
ax.set_zlabel('CENTRAL DISTANCE')

plt.show()

额外说明

  • 读取CSV时添加了names=headers参数,如果你的CSV文件本身已经包含表头,可以去掉这个参数
  • 将marker='-'改为marker='o',因为'-'不是matplotlib支持的3D散点图标记

内容的提问来源于stack exchange,提问作者gl3327

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 12:48:15