Removing axes margins in 3D plot

守給你的承諾、 提交于 2019-12-28 05:54:09

问题


I spent last few days trying to find a way to remove tiny margins from axes in a 3D plot. I tried ax.margins(0) and ax.autoscale_view('tight') and other approaches, but these small margins are still there. In particular, I don't like that the bar histograms are elevated, i.e., their bottom is not at the zero level -- see example image.

In gnuplot, I would use "set xyplane at 0". In matplotlib, since there are margins on every axis on both sides, it would be great to be able to control each of them.

Edit: HYRY's solution below works well, but the 'X' axis gets a grid line drawn over it at Y=0:


回答1:


There is not property or method that can modify this margins. You need to patch the source code. Here is an example:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
###patch start###
from mpl_toolkits.mplot3d.axis3d import Axis
if not hasattr(Axis, "_get_coord_info_old"):
    def _get_coord_info_new(self, renderer):
        mins, maxs, centers, deltas, tc, highs = self._get_coord_info_old(renderer)
        mins += deltas / 4
        maxs -= deltas / 4
        return mins, maxs, centers, deltas, tc, highs
    Axis._get_coord_info_old = Axis._get_coord_info  
    Axis._get_coord_info = _get_coord_info_new
###patch end###

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]):
    xs = np.arange(20)
    ys = np.random.rand(20)

    # You can provide either a single color or an array. To demonstrate this,
    # the first bar of each set will be colored cyan.
    cs = [c] * len(xs)
    cs[0] = 'c'
    ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

The result is:

Edit

To change the color of the grid lines:

for axis in (ax.xaxis, ax.yaxis, ax.zaxis):
    axis._axinfo['grid']['color']  = 0.7, 1.0, 0.7, 1.0

Edit2

Set X & Y lim:

ax.set_ylim3d(-1, 31)
ax.set_xlim3d(-1, 21)



回答2:


I had to tweak the accepted solution slightly, because in my case the x and y axes (but not the z) had an additional margin, which, by printing mins, maxs, deltas, turned out to be deltas * 6.0/11. Here is the updated patch that worked well in my case.

###patch start###
from mpl_toolkits.mplot3d.axis3d import Axis
def _get_coord_info_new(self, renderer):
    mins, maxs, cs, deltas, tc, highs = self._get_coord_info_old(renderer)
    correction = deltas * [1.0/4 + 6.0/11,
                           1.0/4 + 6.0/11,
                           1.0/4]
    mins += correction
    maxs -= correction
    return mins, maxs, cs, deltas, tc, highs
if not hasattr(Axis, "_get_coord_info_old"):
    Axis._get_coord_info_old = Axis._get_coord_info  
Axis._get_coord_info = _get_coord_info_new
###patch end###

(I've also changed the patching logic around a bit, so that editing the function and reloading its module now works as expected in Jupyter.)



来源:https://stackoverflow.com/questions/16488182/removing-axes-margins-in-3d-plot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!