如何删除 3D 投影图中的偏移量?
How to remove offsets in 3D projection plot?
我发现我使用 matplotlib 在 3D 中制作的绘图有轻微的“错位”。这是一个 MWE:
import numpy as np
from matplotlib import pyplot as plt
figure = plt.figure(figsize=(8,10.7))
ax = plt.gca(projection='3d')
ax.plot_surface(np.array([[0, 0], [30, 30]]),
np.array([[10, 10], [10, 10]]),
np.array([[10, 20], [10, 20]]),
rstride=1, cstride=1
)
ax.plot_surface(np.array([[0, 0], [30, 30]]),
np.array([[20, 20], [20, 20]]),
np.array([[10, 20], [10, 20]]),
rstride=1, cstride=1
)
plt.show()
plt.close()
显然,垃圾箱没有正确居中,因为表面似乎从 10.5 开始到 20.5 结束,而不是 10 和 20。如何实现后者?
编辑:恐怕建议的答案有问题。 x轴没有黑实线,默认是这样的:
当我取出建议的包装时,我得到:
不幸的是,当我取出我正在绘制的东西时,这个问题在 Jupyter notebook 中无法重现,但是我想知道你是否可以向我指出我想要的东西必须这样做,在我的情况下,x 轴再次有一条黑线?
这是matplotlib对3DAxis
坐标的处理造成的。它故意移动 mins
和 maxs
以创建一些人为填充:
class Axis(maxis.XAxis):
...
def _get_coord_info(self, renderer):
...
# Add a small offset between min/max point and the edge of the plot
deltas = (maxs - mins) / 12
mins -= 0.25 * deltas
maxs += 0.25 * deltas
...
return mins, maxs, centers, deltas, bounds_proj, highs
从 v3.5.1 开始,没有控制此行为的参数。
但是,我们可以通过 _unpadded
属性使用 functools.wraps
to create a wrapper around Axis._get_coord_info
that unshifts mins
and maxs
. To prevent this wrapper from unshifting multiple times (e.g., when rerunning its Jupyter cell), track the wrapper state:
from functools import wraps
def unpad(f): # where f will be Axis._get_coord_info
@wraps(f)
def wrapper(*args, **kwargs):
mins, maxs, centers, deltas, bounds_proj, highs = f(*args, **kwargs)
mins += 0.25 * deltas # undo original subtraction
maxs -= 0.25 * deltas # undo original addition
return mins, maxs, centers, deltas, bounds_proj, highs
if getattr(f, '_unpadded', False): # bypass if already unpadded
return f
else:
wrapper._unpadded = True # mark as unpadded
return wrapper
在绘图前应用 unpad
包装器:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axis3d import Axis
X = np.array([[0, 0], [30, 30]])
Z = np.array([[10, 20], [10, 20]])
y1, y2, y3 = 10, 16, 20
# wrap Axis._get_coord_info with our unpadded version
Axis._get_coord_info = unpad(Axis._get_coord_info)
fig, ax = plt.subplots(figsize=(8, 10.7), subplot_kw={'projection': '3d'})
ax.plot_surface(X, np.tile(y1, (2, 2)), Z, rstride=1, cstride=1)
ax.plot_surface(X, np.tile(y2, (2, 2)), Z, rstride=1, cstride=1)
ax.plot_surface(X, np.tile(y3, (2, 2)), Z, rstride=1, cstride=1)
plt.show()
我发现我使用 matplotlib 在 3D 中制作的绘图有轻微的“错位”。这是一个 MWE:
import numpy as np
from matplotlib import pyplot as plt
figure = plt.figure(figsize=(8,10.7))
ax = plt.gca(projection='3d')
ax.plot_surface(np.array([[0, 0], [30, 30]]),
np.array([[10, 10], [10, 10]]),
np.array([[10, 20], [10, 20]]),
rstride=1, cstride=1
)
ax.plot_surface(np.array([[0, 0], [30, 30]]),
np.array([[20, 20], [20, 20]]),
np.array([[10, 20], [10, 20]]),
rstride=1, cstride=1
)
plt.show()
plt.close()
显然,垃圾箱没有正确居中,因为表面似乎从 10.5 开始到 20.5 结束,而不是 10 和 20。如何实现后者?
编辑:恐怕建议的答案有问题。 x轴没有黑实线,默认是这样的:
当我取出建议的包装时,我得到:
不幸的是,当我取出我正在绘制的东西时,这个问题在 Jupyter notebook 中无法重现,但是我想知道你是否可以向我指出我想要的东西必须这样做,在我的情况下,x 轴再次有一条黑线?
这是matplotlib对3DAxis
坐标的处理造成的。它故意移动 mins
和 maxs
以创建一些人为填充:
class Axis(maxis.XAxis): ... def _get_coord_info(self, renderer): ... # Add a small offset between min/max point and the edge of the plot deltas = (maxs - mins) / 12 mins -= 0.25 * deltas maxs += 0.25 * deltas ... return mins, maxs, centers, deltas, bounds_proj, highs
从 v3.5.1 开始,没有控制此行为的参数。
但是,我们可以通过 _unpadded
属性使用 functools.wraps
to create a wrapper around Axis._get_coord_info
that unshifts mins
and maxs
. To prevent this wrapper from unshifting multiple times (e.g., when rerunning its Jupyter cell), track the wrapper state:
from functools import wraps
def unpad(f): # where f will be Axis._get_coord_info
@wraps(f)
def wrapper(*args, **kwargs):
mins, maxs, centers, deltas, bounds_proj, highs = f(*args, **kwargs)
mins += 0.25 * deltas # undo original subtraction
maxs -= 0.25 * deltas # undo original addition
return mins, maxs, centers, deltas, bounds_proj, highs
if getattr(f, '_unpadded', False): # bypass if already unpadded
return f
else:
wrapper._unpadded = True # mark as unpadded
return wrapper
在绘图前应用 unpad
包装器:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axis3d import Axis
X = np.array([[0, 0], [30, 30]])
Z = np.array([[10, 20], [10, 20]])
y1, y2, y3 = 10, 16, 20
# wrap Axis._get_coord_info with our unpadded version
Axis._get_coord_info = unpad(Axis._get_coord_info)
fig, ax = plt.subplots(figsize=(8, 10.7), subplot_kw={'projection': '3d'})
ax.plot_surface(X, np.tile(y1, (2, 2)), Z, rstride=1, cstride=1)
ax.plot_surface(X, np.tile(y2, (2, 2)), Z, rstride=1, cstride=1)
ax.plot_surface(X, np.tile(y3, (2, 2)), Z, rstride=1, cstride=1)
plt.show()