subplots forced to have same axis - python

Recently I am plotting 2 graphs at a fig. The data is different and share no common contents. But the final visualizations are forced to have the same axis, I don't understand.
Image here
#################################################################################################
fig, (ax1,ax2) = plt.subplots(1,2, sharey = False, sharex = False)
c = list(len(mydf)*'b')
for i in range(len(c)):
if mydf['percent'][i] > 0.05:
c[i] = 'r'
# ax1 = fig.add_subplot(121)
ax1.bar(range(len(mydf['cdf'])), mydf['cdf'], color = c)
ax1.set_xticks(range(len(mydf['cdf'])))
ax1.set_xticklabels(list(mydf['3D_Attri']), rotation=45)
###########################################################################################3
ax2 = fig.add_subplot(122, projection='3d')
xs = mydf['sphere']
ys = mydf['cylinder']
zs = mydf['addition']
ax2.scatter(xs, ys, zs, zdir='z', s=20, c=c, depthshade=True)
ax2.set_xlabel('sphere')
ax2.set_ylabel('cylinder')
ax2.set_zlabel('addition')
plt.show()

The problem is that you create two subplots in your first line of code. Place a plt.show() directly after that to see that there the wrong axis is already plotted. This will interfere with your 3D graph later, which you simply place on top of it. You have to approach this differently:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
##################################################################################
fig = plt.figure()
c = list(len(mydf)*'b')
for i in range(len(c)):
if mydf['percent'][i] > 0.05:
c[i] = 'r'
ax1 = fig.add_subplot(121)
ax1.bar(range(len(mydf['cdf'])), mydf['cdf'], color = c)
ax1.set_xticks(range(len(mydf['cdf'])))
ax1.set_xticklabels(list(mydf['3D_Attri']), rotation=45)
##################################################################################
ax2 = fig.add_subplot(122, projection='3d')
xs = mydf['sphere']
ys = mydf['cylinder']
zs = mydf['addition']
ax2.scatter(xs, ys, zs, zdir='z', s=20, c=c, depthshade=True)
ax2.set_xlabel('sphere')
ax2.set_ylabel('cylinder')
ax2.set_zlabel('addition')
plt.show()
Output from a toy data set:

Related

Lines missing in 3d scatterplot

I can't find the reason why my plot shows no lines....
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in range(n):
ax.scatter(lys[i][0], lys[i][1], lys[i][2], c='b', marker='o')
ax.plot(x, y, z,'bo', label='Self-avoiding random walk')
ax.legend()
plt.show()
It's because you set the markers in ax.plot to 'bo', which corresponds to blue circle markers only. If you want lines between the markers, you probably want 'b-o', as defined in the docs (check out the 'Format Strings' section under 'Notes'). You need to define the format string as '[marker][line][color]'.
Simple example:
import matplotlib.pyplot as plt
x = y = z = [0, 1, 2]
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x, y, z, 'b-o')
plt.show()
Returns:

Plotting grids across the subplots Python matplotlib

I have tried the following:
d = [1,2,3,4,5,6,7,8,9]
f = [0,1,0,0,1,0,1,1,0]
fig = plt.figure()
fig.set_size_inches(30,10)
ax1 = fig.add_subplot(211)
line1 = ax1.plot(d,marker='.',color='b',label="1 row")
ax2 = fig.add_subplot(212)
line1 = ax2.plot(f,marker='.',color='b',label="1 row")
ax1.grid()
ax2.grid()
plt.show()
I got the following output :
But I was expecting the following output:
How I can get the grids across the two plots?
There is no built-in option to create inter-subplot grids. In this case I'd say an easy option is to create a third axes in the background with the same grid in x direction, such that the gridline can be seen in between the two subplots.
import matplotlib.pyplot as plt
d = [1,2,3,4,5,6,7,8,9]
f = [0,1,0,0,1,0,1,1,0]
fig, (ax1,ax2) = plt.subplots(nrows=2, sharex=True)
ax3 = fig.add_subplot(111, zorder=-1)
for _, spine in ax3.spines.items():
spine.set_visible(False)
ax3.tick_params(labelleft=False, labelbottom=False, left=False, right=False )
ax3.get_shared_x_axes().join(ax3,ax1)
ax3.grid(axis="x")
line1 = ax1.plot(d, marker='.', color='b', label="1 row")
line1 = ax2.plot(f, marker='.', color='b', label="1 row")
ax1.grid()
ax2.grid()
plt.show()
Here is my solution:
import matplotlib.pyplot as plt
x1 = [1,2,3,4,5,6,7,8,9]
x2= [0,1,0,0,1,0,1,1,0]
x3= range(-10,0)
# frameon=False removes frames
# fig, (ax1,ax2, ax3) = plt.subplots(nrows=3, sharex=True, subplot_kw=dict(frameon=False))
fig, (ax1,ax2, ax3) = plt.subplots(nrows=3, sharex=True)
# remove vertical gap between subplots
plt.subplots_adjust(hspace=.0)
ax1.grid()
ax2.grid()
ax3.grid()
ax1.plot(x1)
ax2.plot(x2)
ax3.plot(x3)
Without frames subplot_kw=dict(frameon=False):
An option is to create a single plot then just offset the data. So one set plots above the other.

Force square subplots when plotting a colorbar

I'm trying to generate two subplots side by side, sharing the y axis, with a single colorbar for both.
This is a MWE of my code:
import matplotlib.pyplot as plt
import numpy as np
def rand_data(l, h):
return np.random.uniform(low=l, high=h, size=(100,))
# Generate data.
x1, x2, y, z = rand_data(0., 1.), rand_data(100., 175.), \
rand_data(150., 200.), rand_data(15., 33.)
fig = plt.figure()
cm = plt.cm.get_cmap('RdYlBu')
ax0 = plt.subplot(121)
plt.scatter(x1, y, c=z, cmap=cm)
ax1 = plt.subplot(122)
# make these y tick labels invisible
plt.setp(ax1.get_yticklabels(), visible=False)
plt.scatter(x2, y, c=z, cmap=cm)
cbar = plt.colorbar()
plt.show()
what this returns is a left subplot slightly larger horizontally than the right one since this last includes the colorbar, see below:
I've tried using ax.set_aspect('equal') but since the x axis are not in the same range the result looks awful.
I need both these plots to be displayed squared. How can I do this?
To expend my comment that one can make 3 plots, plot the colorbar() in the 3rd one, the data plots in the 1st and 2nd. This way, if necessary, we are free to do anything we want to the 1st and 2nd plots:
def rand_data(l, h):
return np.random.uniform(low=l, high=h, size=(100,))
# Generate data.
x1, x2, y, z = rand_data(0., 1.), rand_data(100., 175.), \
rand_data(150., 200.), rand_data(15., 33.)
fig = plt.figure(figsize=(12,6))
gs=gridspec.GridSpec(1,3, width_ratios=[4,4,0.2])
ax1 = plt.subplot(gs[0])
ax2 = plt.subplot(gs[1])
ax3 = plt.subplot(gs[2])
cm = plt.cm.get_cmap('RdYlBu')
ax1.scatter(x1, y, c=z, cmap=cm)
SC=ax2.scatter(x2, y, c=z, cmap=cm)
plt.setp(ax2.get_yticklabels(), visible=False)
plt.colorbar(SC, cax=ax3)
plt.tight_layout()
plt.savefig('temp.png')
Updated - here is another option without using GridSpec.
import numpy as np
import matplotlib.pyplot as plt
N = 50
x_vals = np.random.rand(N)
y_vals = np.random.rand(N)
z1_vals = np.random.rand(N)
z2_vals = np.random.rand(N)
minimum_z = min(np.min(z1_vals), np.min(z2_vals))
maximum_z = max(np.max(z1_vals), np.max(z2_vals))
fig, axis_array = plt.subplots(1,2, figsize = (20, 10), subplot_kw = {'aspect':1})
ax0 = axis_array[0].scatter(x_vals, y_vals, c = z1_vals, s = 100, cmap = 'rainbow', vmin = minimum_z, vmax = maximum_z)
ax1 = axis_array[1].scatter(x_vals, y_vals, c = z2_vals, s = 100, cmap = 'rainbow', vmin = minimum_z, vmax = maximum_z)
cax = fig.add_axes([0.95, 0.05, 0.02, 0.95]) #this locates the axis that is used for your colorbar. It is scaled 0 - 1.
fig.colorbar(ax0, cax, orientation = 'vertical') #'ax0' tells it which plot to base the colors on
plt.show()

Matplotlib: Plotting the same graph in two different figures without writting the "plot(x,y)" line twice

I have this simple code that plots exactly the same thing in two different figures (fig1 and fig2). However, I have to write the line ax?.plot(x, y) twice, once for ax1 and once for ax2. How can I have only one plot expression (having multiple redondant ones could be a source of troubles for my more complex code). Something like ax1,ax2.plot(x, y) ... ?
import numpy as np
import matplotlib.pyplot as plt
#Prepares the data
x = np.arange(5)
y = np.exp(x)
#plot fig1
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
#plot fig2
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
#adds the same fig2 plot on fig1
ax1.plot(x, y)
ax2.plot(x, y)
plt.show()
You can either add each axes to a list, like this:
import numpy as np
import matplotlib.pyplot as plt
axes_lst = []
#Prepares the data
x = np.arange(5)
y = np.exp(x)
#plot fig1
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
axes_lst.append(ax1)
#plot fig2
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
axes_lst.append(ax2)
for ax in axes_lst:
ax.plot(x, y)
plt.show()
or you can use this unsupported feature to pull all of the figures in pyplot. Taken from https://stackoverflow.com/a/3783303/1269969
figures=[manager.canvas.figure
for manager in matplotlib._pylab_helpers.Gcf.get_all_fig_managers()]
for figure in figures:
figure.gca().plot(x,y)
Without knowing about matplotlib, you could add all your axes (?) to a list:
to_plot = []
to_plot.append(ax1)
...
to_plot.append(ax2)
...
# apply the same action to each ax
for ax in to_plot:
ax.plot(x, y)
You could then add as many as you like, and the same thing will happen to each.

Matplotlib 3D Scatter Plot with Colorbar

Borrowing from the example on the Matplotlib documentation page and slightly modifying the code,
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
cs = randrange(n, 0, 100)
ax.scatter(xs, ys, zs, c=cs, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
Will give a 3D scatter plot with different colors for each point (random colors in this example). What's the correct way to add a colorbar to the figure, since adding in plt.colorbar() or ax.colorbar() doesn't seem to work.
This produces a colorbar (though possibly not the one you need):
Replace this line:
ax.scatter(xs, ys, zs, c=cs, marker=m)
with
p = ax.scatter(xs, ys, zs, c=cs, marker=m)
then use
fig.colorbar(p)
near the end
Using the above answer did not solve my problem. The colorbar colormap was not linked to the axes (note also the incorrect colorbar limits):
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
data = np.random.rand(3, 100)
x, y, z = data # for show
c = np.arange(len(x)) / len(x) # create some colours
p = ax.scatter(x, y, z, c=plt.cm.magma(0.5*c))
ax.set_xlabel('$\psi_1$')
ax.set_ylabel('$\Phi$')
ax.set_zlabel('$\psi_2$')
ax.set_box_aspect([np.ptp(i) for i in data]) # equal aspect ratio
fig.colorbar(p, ax=ax)
The solution (see here also) is to use cmap in ax.scatter:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
data = np.random.rand(3, 100)
x, y, z = data # for show
c = np.arange(len(x)) / len(x) # create some colours
p = ax.scatter(x, y, z, c=0.5*c, cmap=plt.cm.magma)
ax.set_xlabel('$\psi_1$')
ax.set_ylabel('$\Phi$')
ax.set_zlabel('$\psi_2$')
ax.set_box_aspect([np.ptp(i) for i in data]) # equal aspect ratio
fig.colorbar(p, ax=ax)

Categories