Python matplotlib中的中心原点
我需要帮助自定义我的绘图。我希望画布看起来近似于MacOS Grapher的默认2D图形模板(请参见屏幕截图) 为了澄清-我需要Python matplotlib中的中心原点,python,matplotlib,plot,Python,Matplotlib,Plot,我需要帮助自定义我的绘图。我希望画布看起来近似于MacOS Grapher的默认2D图形模板(请参见屏幕截图) 为了澄清-我需要 中心轴 网格(最好每1个单元增加一个较暗的网格) 带箭头的轴线 origo只有一个零(当我尽力时,我从x轴得到一个零,从y轴得到第二个零),稍微向左移动,所以它不在y轴后面 我真的很感谢你的帮助 居中轴,请参见此处的示例(查找“归零脊椎”): 网格:ax.grid(真) 去除原点处的零:请参见此处设置刻度(…): 你还找了什么 这肯定属于matplotlib带
- 中心轴
- 网格(最好每1个单元增加一个较暗的网格)
- 带箭头的轴线
- origo只有一个零(当我尽力时,我从x轴得到一个零,从y轴得到第二个零),稍微向左移动,所以它不在y轴后面
我真的很感谢你的帮助 居中轴,请参见此处的示例(查找“归零脊椎”): 网格:ax.grid(真) 去除原点处的零:请参见此处设置刻度(…):
你还找了什么 这肯定属于matplotlib带来的麻烦,但现在就来吧。另外,对于基本情况,请查看 <>你可以用几种不同的方式来做这件事,但是为了达到最佳的视觉效果,考虑下面几行的内容。这远不是完美的,但它相当灵活:
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.patheffects
import numpy as np
def center_spines(ax=None, centerx=0, centery=0):
"""Centers the axis spines at <centerx, centery> on the axis "ax", and
places arrows at the end of the axis spines."""
if ax is None:
ax = plt.gca()
# Set the axis's spines to be centered at the given point
# (Setting all 4 spines so that the tick marks go in both directions)
ax.spines['left'].set_position(('data', centerx))
ax.spines['bottom'].set_position(('data', centery))
ax.spines['right'].set_position(('data', centerx - 1))
ax.spines['top'].set_position(('data', centery - 1))
# Draw an arrow at the end of the spines
ax.spines['left'].set_path_effects([EndArrow()])
ax.spines['bottom'].set_path_effects([EndArrow()])
# Hide the line (but not ticks) for "extra" spines
for side in ['right', 'top']:
ax.spines[side].set_color('none')
# On both the x and y axes...
for axis, center in zip([ax.xaxis, ax.yaxis], [centerx, centery]):
# Turn on minor and major gridlines and ticks
axis.set_ticks_position('both')
axis.grid(True, 'major', ls='solid', lw=0.5, color='gray')
axis.grid(True, 'minor', ls='solid', lw=0.1, color='gray')
axis.set_minor_locator(mpl.ticker.AutoMinorLocator())
# Hide the ticklabels at <centerx, centery>
formatter = CenteredFormatter()
formatter.center = center
axis.set_major_formatter(formatter)
# Add offset ticklabels at <centerx, centery> using annotation
# (Should probably make these update when the plot is redrawn...)
xlabel, ylabel = map(formatter.format_data, [centerx, centery])
ax.annotate('(%s, %s)' % (xlabel, ylabel), (centerx, centery),
xytext=(-4, -4), textcoords='offset points',
ha='right', va='top')
# Note: I'm implementing the arrows as a path effect rather than a custom
# Spines class. In the long run, a custom Spines class would be a better
# way to go. One of the side effects of this is that the arrows aren't
# reversed when the axes are reversed!
class EndArrow(mpl.patheffects._Base):
"""A matplotlib patheffect to add arrows at the end of a path."""
def __init__(self, headwidth=5, headheight=5, facecolor=(0,0,0), **kwargs):
super(mpl.patheffects._Base, self).__init__()
self.width, self.height = headwidth, headheight
self._gc_args = kwargs
self.facecolor = facecolor
self.trans = mpl.transforms.Affine2D()
self.arrowpath = mpl.path.Path(
np.array([[-0.5, -0.2], [0.0, 0.0], [0.5, -0.2],
[0.0, 1.0], [-0.5, -0.2]]),
np.array([1, 2, 2, 2, 79]))
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
scalex = renderer.points_to_pixels(self.width)
scaley = renderer.points_to_pixels(self.height)
x0, y0 = tpath.vertices[-1]
dx, dy = tpath.vertices[-1] - tpath.vertices[-2]
azi = np.arctan2(dy, dx) - np.pi / 2.0
trans = affine + self.trans.clear(
).scale(scalex, scaley
).rotate(azi
).translate(x0, y0)
gc0 = renderer.new_gc()
gc0.copy_properties(gc)
self._update_gc(gc0, self._gc_args)
if self.facecolor is None:
color = rgbFace
else:
color = self.facecolor
renderer.draw_path(gc0, self.arrowpath, trans, color)
renderer.draw_path(gc, tpath, affine, rgbFace)
gc0.restore()
class CenteredFormatter(mpl.ticker.ScalarFormatter):
"""Acts exactly like the default Scalar Formatter, but yields an empty
label for ticks at "center"."""
center = 0
def __call__(self, value, pos=None):
if value == self.center:
return ''
else:
return mpl.ticker.ScalarFormatter.__call__(self, value, pos)
当然可以使用matplotlib,但这可能会带来麻烦。如果这是一个选项,TeX和TikZ可能更容易做到这一点。当然,中心轴和网格在TikZ很容易,至少。做得好!看起来确实有很多工作要做;我很高兴我早就放弃了。:-)哇,看起来真的很重。谢谢你推荐什么来代替matplotlib?@Steve-谢谢@mewoshh-在gnuplot中可能会更容易一些。然而,我不知道如何在gnuplot中的轴线上创建箭头(当绘图重新缩放时,箭头会更新)。其余部分(中心轴脊椎)在gnuplot中比较容易,但在matplotlib中也不难。这确实应该内置到matplotlib中。它可能对科学情节没有那么有用,但对教育目的和家庭作业却非常有用。center_spines()很好看,但似乎xlabel和ylabel不再显示了。您还可以修改代码,以便始终显示两个轴吗?这意味着,如果原点不在绘图区域内,则两个带箭头的轴将在其最近的角处相交。
x = np.arange(-5, 5)
y = x
line, = plt.plot(x, y)
center_spines()
plt.axis('equal')
plt.show()