我发现了一些问题,可能是mplcursors
库中的错误。因为已经完成了可重现的代码,所以把它放在下面:
import matplotlib.pyplot as plt
import mplcursors
import numpy as np
import pandas as pd
N = 30
n = [int(i) for i in range(0,N)]
x = np.random.random(N)*10
y = np.random.random(N)*10
z = np.random.random(N)*10
df = pd.DataFrame(data = np.array([n, x, y, z]).T, columns = ['id', 'X', 'Y', 'Z'])
fig = plt.figure(frameon=False, facecolor='yellow', edgecolor='green', dpi=200, figsize=(8,5))
ax = fig.gca(projection='3d')
points = ax.scatter3D(x, y, z, s=5, marker='o', edgecolor='black', linewidth=.5)
def getInfo(sel):
n,x,y,z = df.loc[sel, ['id', 'X', 'Y', 'Z']]
row = "Point: " + str(n) + "\n" + str(x) + ", \n" + str(y) + ", \n" + str(z)
return row
ap = [{'horizontalalignment': 'left', 'verticalalignment': 'top', 'anncoords': 'offset points'}] #, 'position': (8, -8)}]
mc = mplcursors.cursor(points, hover=2, annotation_positions=ap)
mc.connect("add", lambda sel: sel.annotation.set_text( getInfo(sel.index) ))
mc.connect("add", lambda sel: sel.annotation.get_bbox_patch().set(fc="palegreen", alpha=0.75))
plt.show()
错误信息在这里:
Traceback (most recent call last):
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 196, in process
func(*args, **kwargs)
File "C:\Users\cp\Anaconda3\lib\site-packages\mplcursors\_mplcursors.py", line 567, in _on_hover_motion_notify
self._on_select_event(event)
File "C:\Users\cp\Anaconda3\lib\site-packages\mplcursors\_mplcursors.py", line 615, in _on_select_event
self.add_selection(pi)
File "C:\Users\cp\Anaconda3\lib\site-packages\mplcursors\_mplcursors.py", line 412, in add_selection
bbox = ann.get_window_extent(renderer)
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\text.py", line 2403, in get_window_extent
bboxes.append(self.arrow_patch.get_window_extent())
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\patches.py", line 609, in get_window_extent
return self.get_path().get_extents(self.get_transform())
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\patches.py", line 4218, in get_path
_path, fillable = self.get_path_in_displaycoord()
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\patches.py", line 4238, in get_path_in_displaycoord
shrinkB=self.shrinkB * dpi_cor
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\patches.py", line 2775, in __call__
clipped_path = self._clip(path, patchA, patchB)
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\patches.py", line 2728, in _clip
left, right = split_path_inout(path, insideA)
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\cbook\deprecation.py", line 296, in wrapper
return func(*args, **kwargs)
File "C:\Users\cp\Anaconda3\lib\site-packages\matplotlib\bezier.py", line 274, in split_path_inout
ctl_points, command = next(path_iter)
StopIteration
问题在于:
ap = [{'horizontalalignment': 'left', 'verticalalignment': 'top',
'anncoords': 'offset points'}] #, 'position': (8, -8)}]
如果我跳过ap
变量或将position
变量添加到列表中,一切正常。没有别的办法。这样做的缺点是我无法证明没有文本的合理ap
性,并且悬停的位置不会自动选择 -ap
分配时。
如果有人知道在不手动定位悬停框的情况下有理由的解决方案,请回答,但最后这是小问题。