This question already has answers here:
show origin axis (x,y) in matplotlib plot
(3 answers)
Closed 2 years ago.
So I am working on a program that displays the graph of a function over an interval, and the plot size is automatically handled by matplotlib. The only thing is, it resizes without showing x=0 and y=0 cartesian axes. Everything I tried so far, like plt.subplot(), only affects the axes that show at the bottom and left, not the cartesian axes. Is there a way to add the axes in?
Here is some example code:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-2, 1, 100)
f = lambda x: x**2 - 1
plt.plot(x, f(x))
plt.show()
The graph that comes from this looks like this:
which does not show the cartesian axes. Is there a way to add this in, maybe by adding lines at x=0 and y=0?
You can set the spine axis to be in a custom position, like the origin:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2,1,100)
y = x**2
fig, ax = plt.subplots(1, figsize=(6, 4))
ax.plot(x, y)
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.set(ylim=(-1, 4))
Otherwise, you can add a vertical and a horizontal line:
fig, ax = plt.subplots(1, figsize=(6, 4))
ax.plot(x, y)
ax.axhline(0, color='black')
ax.axvline(0, color='black')
You can do it by drawing arrows:
import matplotlib.pyplot as plt
import numpy as np
from pylab import *
x = np.linspace(-2, 1, 100)
f = lambda x: x**2 - 1
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_aspect('equal')
plt.plot(x, f(x))
l,r = ax.get_xlim()
lo,hi = ax.get_ylim()
arrow( l-1, 0, r-l+2, 0, length_includes_head = False, head_width = 0.2 )
arrow( 0, lo-1, 0, hi-lo+2, length_includes_head = True, head_width = 0.2 )
plt.show()
Related
Here is the code I'm running to plot a 2D ellipse on the "z=10 wall" of the plot:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import mpl_toolkits.mplot3d.art3d as art3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Draw a circle on the z=10 'wall'
p = Ellipse((0, 0), 6, 3, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, z= 10, zdir="z")
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_zlim(-10, 10)
plt.show()
However it seems that the depth axis here is considered to be y:
I'd like to have the y axis be what the z axis is right now, the x axis be what the y axis is right now, and the z axis be what the x axis is right now. Would you know how to rearange these axes?
ax.view_init(elev=30, azim=45)
ax.view_init(elev=30, azim=-60)
My code is the following and I believe should produce a chart where a scatter plot is superimposed on a contourf plot (i.e. appears on the foreground)
But that does not happen.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.scatter(examples[:,0], examples[:, 1])
ax.contourf(x, y, Z)
I expected that the scatter plot below would be superimposed on the contourf plot:
plt.scatter(x = examples[:,0], y = examples[:, 1])
Why is this and how the code should be changed?
Just swap contourf and scatter order:
import numpy as np
import matplotlib.pyplot as plt
N = 1000
xl = np.linspace(0, 10, N)
yl = np.linspace(0, 10, N)
x, y = np.meshgrid(xl, yl)
Z = x**2 + y**2
examples = np.random.uniform(low = 0, high = 10, size = (10, 2))
fig, ax = plt.subplots()
ax.contourf(x, y, Z)
ax.scatter(examples[:,0], examples[:, 1], color = 'red')
plt.show()
The last plot line you write overlaps the previous one.
I am using mplot3d from the mpl_toolkits library. When displaying the 3D surface on the figure I'm realized the axis were not positioned as I wished they would.
Let me show, I have added to the following screenshot the position of each axis:
Is there a way to change the position of the axes in order to get this result:
Here's the working code:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
ax = Axes3D(plt.figure())
def f(x,y) :
return -x**2 - y**2
X = np.arange(-1, 1, 0.02)
Y = np.arange(-1, 1, 0.02)
X, Y = np.meshgrid(X, Y)
Z = f(X, Y)
ax.plot_surface(X, Y, Z, alpha=0.5)
# Hide axes ticks
ax.set_xticks([-1,1])
ax.set_yticks([-1,1])
ax.set_zticks([-2,0])
ax.set_yticklabels([-1,1],rotation=-15, va='center', ha='right')
plt.show()
I have tried using xaxis.set_ticks_position('left') statement, but it doesn't work.
No documented methods, but with some hacking ideas from https://stackoverflow.com/a/15048653/1149007 you can.
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = ax = fig.add_subplot(111, projection='3d')
ax.view_init(30, 30)
def f(x,y) :
return -x**2 - y**2
X = np.arange(-1, 1, 0.02)
Y = np.arange(-1, 1, 0.02)
X, Y = np.meshgrid(X, Y)
Z = f(X, Y)
ax.plot_surface(X, Y, Z, alpha=0.5)
# Hide axes ticks
ax.set_xticks([-1,1])
ax.set_yticks([-1,1])
ax.set_zticks([-2,0])
ax.xaxis._axinfo['juggled'] = (0,0,0)
ax.yaxis._axinfo['juggled'] = (1,1,1)
ax.zaxis._axinfo['juggled'] = (2,2,2)
plt.show()
I can no idea of the meaning of the third number in triples. If set zeros nothing changes in the figure. So should look in the code for further tuning.
You can also look at related question Changing position of vertical (z) axis of 3D plot (Matplotlib)? with low level hacking of _PLANES property.
Something changed, code blow doesn't work, all axis hide...
ax.xaxis._axinfo['juggled'] = (0,0,0)
ax.yaxis._axinfo['juggled'] = (1,1,1)
ax.zaxis._axinfo['juggled'] = (2,2,2)
I suggest using the plot function to create a graph
In the reference, they are described as:
axis('equal')
changes limits of x or y axis so that equal increments of x and y have the same length; a circle is
circular.:
axis('scaled')
achieves the same result by changing the dimensions of the plot box instead of the axis data limits.:
But I did not understand the part 'by changing the dimensions of the plot box'.
So I compared directly
import numpy as np
import matplotlib.pyplot as plt
plt.close('all')
x = np.array(np.linspace(-np.pi, np.pi))
y = np.sin(x)
ax1 = plt.subplot(2, 1, 1)
ax1 = plt.plot(x, y)
plt.axis('scaled')
ax1 = plt.subplot(2, 1, 2)
plt.plot(x, y)
plt.axis('equal')
There is only a slight difference that the width is shorter when plotted with plt.axis('scaled').
How can I know the difference better?
I think the difference becomes more apparent, if you use different data.
import numpy as np
import matplotlib.pyplot as plt
x = np.array(np.linspace(-np.pi, np.pi))
y = np.sin(x)*np.pi
ax1 = plt.subplot(2, 1, 1)
ax1 = plt.plot(x, y)
plt.axis('scaled')
ax1 = plt.subplot(2, 1, 2)
plt.plot(x, y)
plt.axis('equal')
plt.show()
So the difference is if the axes around the plot are changed according to the aspect, or if they stay the same as in a usual subplot and are scaled such, that the aspect of the plot data is equal.
I have two subplots that share the x-axes. The first one has data and a fit function, in the second one is the difference between the data and the fit function. In the figure both subplots have the same y axis size (in pixels). Now i want the y axis of the data and the fit to be bigger than the axis of the errors. my code is the following:
import matplotlib.pyplot as plt
f, axarr = plt.subplots(2, sharex=True,figsize=(15, 12))
axarr[0].scatter(x, data , facecolors='none', edgecolors='crimson')
axarr[0].plot(x, fit, color='g',linewidth=1.5)
axarr[0].set_ylim([18,10])
axarr[1].plot(x,data-fit,color='k',linewidth=width)
axarr[1].set_ylim([-0.4,0.4])
yticks[-1].label1.set_visible(False)
plt.subplots_adjust(hspace=0.)
is there any code that sets the size of the second plot?
Take a look at this example, using gridspec. I believe it is exactly what you want. Below is the example adopted for your case. Edited to also share the x-axis
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
# generate some data
x = np.arange(0, 10, 0.2)
y = np.sin(x)
# plot it
fig = plt.figure(figsize=(8, 6))
gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1])
ax0 = plt.subplot(gs[0])
ax1 = plt.subplot(gs[1], sharex=ax0) # <---- sharex=ax0 will share ax1 with ax2
ax0.plot(x, y)
ax1.plot(y, x)
plt.show()
Or even simpler by following Hagnes answer in the first link:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 10, 0.2)
y = np.sin(x)
f, (a0, a1) = plt.subplots(2,1, gridspec_kw = {'height_ratios':[1, 3]}, sharex=True) # <---- sharex=True will share the xaxis between the two axes
a0.plot(x, y)
a1.plot(y, x)
plt.show()