fixing the y scale in python matplotlib - python

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.

Related

matplotlib: reduce axes width in subplots

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

Python - increase matplotlib figure size with dual x axis

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()

plotting with pcolormesh, changing axis

Supppose I am plotting a assymetric matrix with pcolormesh:
import prettyplotlib as ppl
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
fig, ax = plt.subplots(1)
ppl.pcolormesh(fig, ax, np.random.randn(10,80))
plt.show()
Now I want to change the x-axis such that its extents are for example -500 to 500 without changing the plot, only the labels of the x-axis, the same for y-axis. How can I accomplish that?
After the ppl.pcolormesh command you can define the ticklables directly using
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels)
where xticklabels is an array of your desired labels and xticks are the values at which the labels should apply.

Set the plot y-axis and x-axis ratio equal

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.

Matplotlib - imshow twiny() problems

I am trying to have two inter-depedent x-axis in a matplotlib imshow() plot. I have bottom x-axis as the radius squared and I want the top as just the radius. I have tried so far:
ax8 = ax7.twiny()
ax8._sharex = ax7
fmtr = FuncFormatter(lambda x,pos: np.sqrt(x) )
ax8.xaxis.set_major_formatter(fmtr)
ax8.set_xlabel("Radius [m]")
where ax7 is the y-axis and the bottom x-axis (or radius squared). Instead of getting the sqrt (x_bottom) as the ticks at the top I just get a range from 0 to 1. How can I fix this?
Thanks a lot in advance.
You're misunderstanding what twiny does. It makes a completely independent x-axis with a shared y-axis.
What you want to do is have a different formatter with a linked axis (i.e. sharing the axis limits but nothing else).
The simple way to do this is to manually set the axis limits for the twinned axis:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
fig, ax1 = plt.subplots()
ax1.plot(range(10))
ax2 = ax1.twiny()
formatter = FuncFormatter(lambda x, pos: '{:0.2f}'.format(np.sqrt(x)))
ax2.xaxis.set_major_formatter(formatter)
ax2.set_xlim(ax1.get_xlim())
plt.show()
However, as soon as you zoom or interact with the plot, you'll notice that the axes are unlinked.
You could add an axes in the same position with both shared x and y axes, but then the tick formatters are shared, as well.
Therefore, the easiest way to do this is using a parasite axes.
As a quick example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
from mpl_toolkits.axes_grid1.parasite_axes import SubplotHost
fig = plt.figure()
ax1 = SubplotHost(fig, 1,1,1)
fig.add_subplot(ax1)
ax2 = ax1.twin()
ax1.plot(range(10))
formatter = FuncFormatter(lambda x, pos: '{:0.2f}'.format(np.sqrt(x)))
ax2.xaxis.set_major_formatter(formatter)
plt.show()
Both this and the previous plot will look identical at first. The difference will become apparent when you interact (e.g. zoom/pan) with the plot.

Categories