I'd like to make a stacked area chart but it would increase stepwise, like the stairs plot.
It is a cumulative chart, so a stepwise increase would make more sense.
How can it be done?
plt.stackplot accepts extra kwargs which are sent to plt.fill_between. One of those is step='post', creating a horizontal line starting with the given value. (In contrast, step='pre' has the horizontal lines at the height of the ending positions.)
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(1, 6)
y1 = np.random.rand(5) + 1
y2 = np.random.rand(5) + 2
y3 = np.random.rand(5) + 3
plt.stackplot(x, y1, y2, y3, step='post', labels=['A', 'B', 'C'])
plt.xticks(x)
plt.legend()
plt.show()
Related
I am trying to clip data to within the axes bounds when using subplots to create multiple plots.
By setting clip_on = True the data is clipped to the figure but still is shown in the neighboring plot above, but I don't want this to happen. The code below reproducers the issue where the blue line appears in the first plot overtop of the red line.
import matplotlib as mpl
import numpy as np
fig, ax = mpl.pyplot.subplots(2,1)
x = np.linspace(-10, 10, 1000)
y1 = x**2 + 2*x + 2
y2 = x**2 + 2*x + 3
ax[0].set_ylim(0, 5)
ax[0].plot(x, y1, color = 'red', clip_on = True)
ax[1].set_ylim(0, 5)
ax[1].plot(x, y2, clip_on = True)
I'm facing a problem in showing the legend in the correct format using matplotlib.
EDIT: I have 4 subplots in a figure in 2 by 2 format and I want legend only on the first subplot which has two lines plotted on it. The legend that I got using the code attached below contained endless entries and extended vertically throughout the figure. When I use the same code using linspace to generate fake data the legend works absolutely fine.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import os
#------------------set default directory, import data and create column output vectors---------------------------#
path="C:/Users/Pacman/Data files"
os.chdir(path)
data =np.genfromtxt('vrp.txt')
x=np.array([data[:,][:,0]])
y1=np.array([data[:,][:,6]])
y2=np.array([data[:,][:,7]])
y3=np.array([data[:,][:,9]])
y4=np.array([data[:,][:,11]])
y5=np.array([data[:,][:,10]])
nrows=2
ncols=2
tick_l=6 #length of ticks
fs_axis=16 #font size of axis labels
plt.rcParams['axes.linewidth'] = 2 #Sets global line width of all the axis
plt.rcParams['xtick.labelsize']=14 #Sets global font size for x-axis labels
plt.rcParams['ytick.labelsize']=14 #Sets global font size for y-axis labels
plt.subplot(nrows, ncols, 1)
ax=plt.subplot(nrows, ncols, 1)
l1=plt.plot(x, y2, 'yo',label='Flow rate-fan')
l2=plt.plot(x,y3,'ro',label='Flow rate-discharge')
plt.title('(a)')
plt.ylabel('Flow rate ($m^3 s^{-1}$)',fontsize=fs_axis)
plt.xlabel('Rupture Position (ft)',fontsize=fs_axis)
# This part is not working
plt.legend(loc='upper right', fontsize='x-large')
#Same code for rest of the subplots
I tried to implement a fix suggested in the following link, however, could not make it work:
how do I make a single legend for many subplots with matplotlib?
Any help in this regard will be highly appreciated.
If I understand correctly, you need to tell plt.legend what to put as legends... at this point it is being loaded empty. What you get must be from another source. I have quickly the following, and of course when I run fig.legend as you do I get nothing.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.1, 0.4, 0.7])
ax2 = fig.add_axes([0.55, 0.1, 0.4, 0.7])
x = np.arange(0.0, 2.0, 0.02)
y1 = np.sin(2*np.pi*x)
y2 = np.exp(-x)
l1, l2 = ax1.plot(x, y1, 'rs-', x, y2, 'go')
y3 = np.sin(4*np.pi*x)
y4 = np.exp(-2*x)
l3, l4 = ax2.plot(x, y3, 'yd-', x, y4, 'k^')
fig.legend(loc='upper right', fontsize='x-large')
#fig.legend((l1, l2), ('Line 1', 'Line 2'), 'upper left')
#fig.legend((l3, l4), ('Line 3', 'Line 4'), 'upper right')
plt.show()
I'd suggest doing one by one, and then applying for all.
It is useful to work with the axes directly (ax in your case) when when working with subplots. So if you set up two plots in a figure and only wish to have a legend in your second plot:
t = np.linspace(0, 10, 100)
plt.figure()
ax1 = plt.subplot(2, 1, 1)
ax1.plot(t, t * t)
ax2 = plt.subplot(2, 1, 2)
ax2.plot(t, t * t * t)
ax2.legend('Cubic Function')
Note that when creating the legend, I am doing so on ax2 as opposed to plt. If you wish to create a second legend for the first subplot, you can do so in the same way but on ax1.
I have generated a plot that shows a topographic profile with points along the profile that represent dated points. However, these dated points also have symmetric uncertainty values/error bars (that typically vary for each point).
In this example, I treat non-dated locations as 'np.nan'. I would like to add uncertainty values to the y2 axis (Mean Age) with defined uncertainty values as y2err.
Everytime I use the ax2.errorbar( ... ) line, my graph is squeezed and distorted.
import numpy as np
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
#Longitude = x; Elevation = y
x = (-110.75696,-110.75668,-110.75640,-110.75612,-110.75584,-110.75556,-110.75528)
y = (877,879,878,873,871,872,872)
ax1.plot(x, y)
ax1.set_xlabel('Longitude')
# Make the y-axis label, ticks and tick labels match the line color.
ax1.set_ylabel('Elevation', color='b')
ax1.tick_params('y', colors='b')
ax2 = ax1.twinx()
# Mean Age, np.nan = 0.0
y2 = (np.nan,20,np.nan,np.nan,np.nan,np.nan,np.nan)
y2err = (np.nan,5,np.nan,np.nan,np.nan,np.nan,np.nan)
ax2.scatter(x, y2, color='r')
#add error bars to scatter plot points
# (??????) ax2.errorbar(x, y, y2, y2err, capsize = 0, color='black')
ax2.set_ylim(10,30)
ax2.set_ylabel('Mean Age', color='r')
ax2.tick_params('y', colors='r')
fig.tight_layout()
plt.show()
If I do not apply the ax2.errorbar... line my plot looks like the first image, which is what I want but with the points showing uncertainty values (+/- equal on both side of point in the y-axis direction).
Plot of Elevation vs Age without error bars
When I use the ax2.errorbar line it looks like the second image:
Plot when using ax2.errorbar line
Thanks!
I want to have a scatter plot with colormap for edgecolors but no facecolors.
When I use facecolor='None', it does not work.
import numpy as np
import matplotlib.pyplot as plt
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radii
plt.scatter(x, y, s=area,c=colors,facecolors='None',cmap="gist_rainbow", alpha=0.5)
plt.show()
Any solution?
The c argument will affect facecolor and edgecolor simultaneouly, the arguments facecolor and edgecolor are hence ignored.
A solution would be not to use the c argument together with a colormap, but instead use facecolors and edgecolors alone. In this case facecolors can be set to "None" and edgecolors can be given a list of colors to use.
To create this list, the same colormap can be applied.
c = plt.cm.gist_rainbow(colors)
plt.scatter(x, y, s=area,facecolors="None", edgecolors=c, lw=1,alpha=0.5)
A complete example:
import numpy as np
import matplotlib.pyplot as plt
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radii
c = plt.cm.gist_rainbow(colors)
plt.scatter(x, y, s=area,facecolors="None", edgecolors=c, lw=2,alpha=0.5)
plt.show()
The problem is that color= overrides the facecolors= argument.
The solution I came up with is to get the PathCollection returned by pyplot.scatter() and then change the facecolor directly. Note that you probably need to increase the line width to see the edges better.
import numpy as np
import matplotlib.pyplot as plt
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radii
a = plt.scatter(x, y, s=area,c=colors,facecolor='none',lw=2,cmap="gist_rainbow", alpha=0.5)
a.set_facecolor('none')
plt.show()
I know this has been dead for a while, but I wanted to add my experience as I just encountered this same problem.
I prefer Diziet's method as passing the PathCollection object to a colorbar and having it match the cmap used in the scatter plot works exactly as it would if you didn't alter the facecolors.
With the accepted solution, however, I encountered some odd behavior where even after removing the cmap argument from the ax.scatter call the scatter plot edge colormap and the colorbar colormap didn't match.
This is what I have done so far. My problen, however, is that I can't print the values/scale on the y-axis of a bar plot? Any ideas? What other stylings whould I add?
import seaborn as sb
from matplotlib import pyplot
%matplotlib inline
sb.axes_style("white")
sb.set_style("ticks")
sb.set_context("talk")
x1 = np.array(['U', 'G'])
x2 = np.array(['H', 'W'])
f, (ax1, ax2) = pyplot.subplots(1, 2, figsize=(12, 6))
y1 = np.array([831824, 3306662])
y2 = np.array([1798043, 1508619])
sb.barplot(x1, y1, ci=None, palette="Blues", hline=.0001, ax=ax1)
sb.barplot(x1, y2, ci=None, palette="Reds", hline=.0001, ax=ax2)
ax1.set_ylabel("Occurences")
ax1.set_xlabel("Totals")
ax2.set_ylabel("Occurences")
ax2.set_xlabel("Types")
sb.despine(bottom=True)
pyplot.setp(f.axes, yticks=[])
pyplot.tight_layout(h_pad=3)
sb.despine()
Based on #john-cipponeri's answer:
Using functions operating on axes called using pyplot.* only operate on the last opened axis, in your case ax2, which is the the right plot. Use the axis instance to take it effect where you want. Replace tour last block of your code with this one and I hope it corresponds to your expected plot:
ax1.grid(axis='y', linestyle='-')
ax2.grid(axis='y', linestyle='-')
pyplot.tight_layout(h_pad=3)
sb.despine()
You can try a line style.
pyplot.grid(axis='y', linestyle='-')