import numpy as np
import matplotlib.pyplot as plt
plt.figure(1)
plt.subplot(211)
xs = np.linspace(-5,5,500)
ys = np.sqrt(5**2 - xs**2)
plt.plot(xs,ys)
plt.plot(xs,-ys)
plt.subplot(212)
plt.plot(xs, xs**2)
plt.show()
here is the code i generate, was wondering that if i want keep the upper plot x and y ratio be 1:1 so that the ball will always look round no matter how many subplot inside this figure.
I tried to find it from the website, seems not a simple solution..
When you create your subplot, you can tell it:
plt.subplot(211, aspect='equal')
If you've already created the subplot, you have to grab the current axes, which you can do using plt.gca, then call the set_aspect method:
plt.gca().set_aspect('equal')
Or, you can keep track of the axes from the beginning:
ax = plt.subplot(211)
ax.set_aspect('equal')
You may have to call
plt.draw()
In order to update the plot.
Related
I want to draw multiple bar plots with the same y-scale, and so I need the y-scale to be consistent.
For this, I tried using ylim() after yscale()
plt.yscale("log")
plt.ylim(top=2000)
plt.show()
However, python keeps autoscaling the intermittent values depending on my data.
Is there a way to fix this?
overlayed graphs
import numpy as np
import matplotlib.pyplot as plt
xaxis = np.arange(10)
yaxis = np.random.rand(10)*100
fig = plt.subplots(figsize =(10, 7))
plt.bar(xaxis, yaxis, width=0.8, align='center', color='y')
# show graph
plt.yscale("log")
plt.ylim(top=2000)
plt.show()
You can set the y-axis tick labels manually. See yticks for an example. In your case, you will have to do this for each plot to have consistent axes.
(Heavily edited:)
In python matplotlib, I want to plot y against x with two xscales, the lower one with linear ticks and the upper one with logarithmic ticks.
The lower x values are an arbitrary function of the upper ones (in this case the mapping is func(x)=np.log10(1.0+x)). Corollary: The upper x tick positions are the same arbitrary function of the lower ones.
The positions of the data points and the tick positions for both axes must be decoupled.
I want the upper axis's logarithmic tick positions and labels to be as tidy as possible.
What is the best way to produce such a plot?
Related: http://matplotlib.1069221.n5.nabble.com/Two-y-axis-with-twinx-only-one-of-them-logscale-td18255.html
Similar (but unanswered) question?: Matplotlib: how to set ticks of twinned axis in log plot
Could be useful: https://stackoverflow.com/a/29592508/1021819
You may find Axes.twiny() and Axes.semilogx() useful.
import numpy as np
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
x = np.arange(0.01, 10.0, 0.01) # x-axis range
y = np.sin(2*np.pi*x) # simulated signal to plot
ax1.plot(x, y, color="r") # regular plot (red)
ax1.set_xlabel('x')
ax2 = ax1.twiny() # ax1 and ax2 share y-axis
ax2.semilogx(x, y, color="b") # semilog plot (blue)
ax2.set_xlabel('semilogx')
plt.show()
Here is an attempt at an answer after speaking to a few people and with thanks to #BusyBeaver.
I agree the question was ill-posed and will amend it to clarify (help welcome!).
I do think this is a useful one to have written down on stackoverflow.
Code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator
# Necessary functions
def tick_function(x):
"""Specify tick format"""
return ["%2.f" % i for i in x]
def func(x):
"""This can be anything you like"""
funcx=np.log10(1.0+x)
return funcx
z=np.linspace(0.0,4.0,20)
np.random.seed(seed=1234)
y=np.random.normal(10.0,1.0,len(z))
# Set up the plot
fig,ax1 = subplots()
ax1.xaxis.set_minor_locator(AutoMinorLocator())
ax1.yaxis.set_minor_locator(AutoMinorLocator())
# Set up the second axis
ax2 = ax1.twiny()
# The tick positions can be at arbitrary positions
zticks=np.arange(z[0],z[-1]+1)
ax2.set_xticks(func(zticks))
ax2.set_xticklabels(tick_function(zticks))
ax2.set_xlim(func(z[0]),func(z[-1]))
ax1.set_ylim(5.0,15.0)
ax1.set_xlabel(r'$\log_{10}\left(1+z\right)$')
ax2.set_xlabel(r'$z$')
ax1.set_ylabel('amplitude/arb. units')
plt.tick_params(axis='both',which = 'major', labelsize=8, width=2)
plt.tick_params(axis='both',which = 'minor', labelsize=8, width=1)
_=ax1.plot(func(z),y,'k.')
plt.savefig('lnopz2.png')
I am not sure how to control the upper ax2 minor ticks (e.g. every 0.5).
I have a matplotlib bar chart, which bars are colored according to some rules through a colormap. I need a colorbar on the right of the main axes, so I added a new axes with
fig, (ax, ax_cbar) = plt.subplots(1,2)
and managed to draw my color bar in the ax_bar axes, while I have my data displayed in the ax axes. Now I need to reduce the width of the ax_bar, because it looks like this:
How can I do?
Using subplots will always divide your figure equally. You can manually divide up your figure in a number of ways. My preferred method is using subplot2grid.
In this example, we are setting the figure to have 1 row and 10 columns. We then set ax to be the start at row,column = (0,0) and have a width of 9 columns. Then set ax_cbar to start at (0,9) and has by default a width of 1 column.
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,6))
num_columns = 10
ax = plt.subplot2grid((1,num_columns), (0,0), colspan=num_columns-1)
ax_cbar = plt.subplot2grid((1,num_columns), (0,num_columns-1))
The ususal way to add a colorbar is by simply putting it next to the axes:
fig.colorbar(sm)
where fig is the figure and sm is the scalar mappable to which the colormap refers. In the case of the bars, you need to create this ScalarMappable yourself. Apart from that there is no need for complex creation of multiple axes.
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
fig , ax = plt.subplots()
x = [0,1,2,3]
y = np.array([34,40,38,50])*1e3
norm = matplotlib.colors.Normalize(30e3, 60e3)
ax.bar(x,y, color=plt.cm.plasma_r(norm(y)) )
ax.axhline(4.2e4, color="gray")
ax.text(0.02, 4.2e4, "42000", va='center', ha="left", bbox=dict(facecolor="w",alpha=1),
transform=ax.get_yaxis_transform())
sm = plt.cm.ScalarMappable(cmap=plt.cm.plasma_r, norm=norm)
sm.set_array([])
fig.colorbar(sm)
plt.show()
If you do want to create a special axes for the colorbar yourself, the easiest method would be to set the width already inside the call to subplots:
fig , (ax, cax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios" : [10,1]})
and later put the colorbar to the cax axes,
fig.colorbar(sm, cax=cax)
Note that the following questions have been asked for this homework assignment already:
Point picker event_handler drawing line and displaying coordinates in matplotlib
Matplotlib's widget to select y-axis value and change barplot
Display y axis value horizontal line drawn In bar chart
How to change colors automatically once a parameter is changed
Interactively Re-color Bars in Matplotlib Bar Chart using Confidence Intervals
I have a chart using matplotlib that uses the twinx() function to display two different plots with different y values:
plt.plot(Current_Time[1000:66000],Avg_Duration[1000:66000],color='blue',label="Average Duration of All Parked Cars")
#plt.figure(figsize=(10,10))
plt.legend(loc='upper left')
plt.ylim(0,50000)
plt.ylabel('Duration in Seconds')
plt.xticks(rotation=90)
plt2=plt.twinx()
#plt2.figure(figsize=(10,10))
plt2.plot(Current_Time[1000:66000],Quantity[1000:66000],color='purple',label='Quantity of Cars Parked')
plt2.set_ylabel('Cars Parked')
plt2.legend(loc='upper right')
plt.show()
The issue I am having is when I try to increase the plot size, it separates the charts. Is there a way to increase the plot size and not split into two charts?
It's sure possible to create twin axes in a figure of any size. One just has to make sure to understand the code one's writing. I.e. don't create a new figure using figure and then complain that there is a second figure appearing.
Sticking to the matplotlib state machine interface, a solution could look like this:
import matplotlib.pyplot as plt
import numpy as np
#get data
x=np.arange(40)
y=np.random.rand(len(x))*20000+30000
y2=np.random.rand(len(x))*0.5
#create a figure
plt.figure(figsize=(10,10))
#plot to first axes
plt.plot(x,y,color='blue',label="label1")
plt.ylim(0,50000)
plt.ylabel('ylabel1')
plt.xticks(rotation=90)
#create twin axes
ax2=plt.gca().twinx()
#plot to twin axes
plt.plot(x,y2,color='purple',label='label2')
plt.ylabel('ylabel2')
plt.legend(loc='upper right')
plt.show()
Or, if you prefer the matplotlib API:
import matplotlib.pyplot as plt
import numpy as np
#get data
x=np.arange(40)
y=np.random.rand(len(x))*20000+30000
y2=np.random.rand(len(x))*0.5
#create a figure
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
#plot to first axes
ax.plot(x,y,color='blue',label="label1")
ax.set_ylim(0,50000)
ax.set_ylabel('ylabel1')
ax.set_xticklabels(ax.get_xticklabels(),rotation=90)
#create twin axes
ax2=ax.twinx()
#plot to twin axes
ax2.plot(x,y2,color='purple',label='label2')
ax2.set_ylabel('ylabel2')
h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax.legend(handles=h1+h2, labels=l1+l2, loc='upper right')
plt.show()
I am trying to produce a scatter plot that has two different y-axes and also a colorbar.
Here is the pseudo-code used:
#!/usr/bin/python
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure()
ax1 = fig.add_subplot(111)
plt.scatter(xgrid,
ygrid,
c=be, # set colorbar to blaze efficiency
cmap=cm.hot,
vmin=0.0,
vmax=1.0)
cbar = plt.colorbar()
cbar.set_label('Blaze Efficiency')
ax2 = ax1.twinx()
ax2.set_ylabel('Wavelength')
plt.show()
And it produces this plot:
My question is, how do you use a different scale for the "Wavelength" axes, and also, how do you move the colorbar more to right so that it is not in the Wavelength's way?
#OZ123 Sorry that I took so long to respond. Matplotlib has extensible customizability, sometimes to the point where you get confused to what you are actually doing. Thanks for the help on creating separate axes.
However, I didn't think I needed that much control, and I ended up just using the PAD keyword argument in
fig.colorbar()
and this provided what I needed.
The pseudo-code then becomes this:
#!/usr/bin/python
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure()
ax1 = fig.add_subplot(111)
mappable = ax1.scatter(xgrid,
ygrid,
c=be, # set colorbar to blaze efficiency
cmap=cm.hot,
vmin=0.0,
vmax=1.0)
cbar = fig.colorbar(mappable, pad=0.15)
cbar.set_label('Blaze Efficiency')
ax2 = ax1.twinx()
ax2.set_ylabel('Wavelength')
plt.show()
Here is to show what it looks like now::
the plt.colorbar() is made for really simple cases, e.g. not really thought for a plot with 2 y-axes.
For a fine grained control of the colorbar location and properties you should almost always rather work with colorbar specifying on which axes you want to plot the colorbar.
# on the figure total in precent l b w , height
cbaxes = fig.add_axes([0.1, 0.1, 0.8, 0.05]) # setup colorbar axes.
# put the colorbar on new axes
cbar = fig.colorbar(mapable,cax=cbaxes,orientation='horizontal')
Note that colorbar takes the following keywords:
keyword arguments:
cax
None | axes object into which the colorbar will be drawn ax
None | parent axes object from which space for a new
colorbar axes will be stolen
you could also see here a more extended answer of mine regarding figure colorbar on separate axes.