I am trying to add a line to mark quantiles for every variable in a polar chart.
When I try axvline it only draws in the first axis
axes1 = plt.gca(projection='polar')
axes1.axvline(x=0, ymin=0.2,ymax=0.6, color='k',lw=3,alpha=0.5)
I want to add a different mark for every axis but I don't know how to iterate over the 5 axes of the example.
You can divide the circle (2 π) into 5 to obtain an x-coordinate for each of the 5 directions.
import matplotlib.pyplot as plt
import numpy as np
axes1 = plt.gca(projection='polar')
xs = np.linspace(0, 2 * np.pi, 5, endpoint=False) + np.pi / 2
for x in xs:
axes1.axvline(x=x, ymin=0.2, ymax=0.6, color='r', lw=3, alpha=0.5)
for ls in [':', '-']:
y = np.random.uniform(0.3, 1, 5)
plt.plot(np.concatenate([xs, xs[:1]]), np.concatenate([y, y[:1]]), color='g', ls=ls)
plt.fill_between(np.concatenate([xs, xs[:1]]), np.concatenate([y, y[:1]]), color='g', alpha=0.2)
plt.xticks(xs % (2 * np.pi))
plt.show()
Related
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()
I'm using this code from matplotlib website to generate gif through list of images.
https://matplotlib.org/gallery/animation/dynamic_image2.html
However, I'm struggling to figure out how to make it work if I have subplot with two axes inside it. Thus, it is as if I have two images, which one should I append to the list?
EDIT: sample code:
ims = []
for i in range(60):
x += np.pi / 15.
y += np.pi / 20.
im = plt.imshow(f(x, y), animated=True)
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
repeat_delay=1000)
As explained in the page you linked, the array of artists passed to ArtistAnimation is a list of lists, each element of the list corresponds to one frame, where all the elements of the "inner" lists are updated.
Therefore
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, (ax1, ax2) = plt.subplots(1,2)
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
# ims is a list of lists, each row is a list of artists to draw in the
# current frame; here we are just animating one artist, the image, in
# each frame
ims = []
for i in range(60):
x += np.pi / 15.
y += np.pi / 20.
im1 = ax1.imshow(f(x, y), animated=True)
im2 = ax2.imshow(np.random.random(size=(100,120)))
ims.append([im1,im2])
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
repeat_delay=1000)
I have data sets like (x,y,(z1,z2,z3..)). I am trying
plt.pcolor(x,y,z1)
plt.pcolor(x,y,z2)
plt.pcolor(x,y,z3)
plt.colorbar()
plt.show()
This is showing only the pcolor plot of the last data set. How can I plot all in same plot and same colorbar scale?
You could try with subplots, and make sure all the images with the same intensity scale (use the same vmin and vmax arguments of pcolor() for all your images). Below is an example:
import numpy as np
import matplotlib.pyplot as plt
dx, dy = 0.15, 0.05
y, x = np.mgrid[slice(-3, 3 + dy, dy),
slice(-3, 3 + dx, dx)]
z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
z1 = z[:-1, :-1]
z2 = z[:-1, :-1]
z3 = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()
data = [[x,y,z1],[x,y,z2],[x,y,z3]]
# Plot each slice as an independent subplot
fig, axes = plt.subplots(nrows=1, ncols=3)
for dat, ax in zip(data, axes.flat):
# The vmin and vmax arguments specify the color limits
pc = ax.pcolor(dat[0],dat[1],dat[2], vmin=z_min, vmax=z_max)
# Make an axis for the colorbar on the right side
cax = fig.add_axes([0.9, 0.1, 0.03, 0.8])
fig.colorbar(pc, cax=cax)
plt.show()
It will show like this:
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.
Is there a way to add two ticks (ex. two letters) along with existing ticks (numbers)?
I have:
but want to add two ticks (letters "a" and "b"). Running the following code deletes the numbers and leaves only letters, however I want to have both.
ax.set_xticks((a, b))
ax.set_xticklabels(('$a$', '$b$'), size='xx-large')
It's easiest to use annotate instead of placing ticks.
For example, let's start by approximately reproducing your example plot:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(2.8, 11, 100)
y = 0.2 * np.exp(-0.05 * x**2) + 0.01
fig, ax = plt.subplots()
ax.fill_between(x, y, alpha=0.3, label='surface', lw=2,
edgecolor='orange', facecolor='goldenrod')
ax.plot(x, y, color='darkred', lw=2, label='interpolated polinom')
ax.legend(fancybox=True, shadow=True)
ax.grid(ls=':')
ax.set_ylabel(r'$F[N]$', size=18)
ax.set_xlabel(r'$h[cm]$', size=18)
ax.spines['bottom'].set(linewidth=2)
plt.show()
We could add the "sub ticks" you want with:
labelpad = ax.xaxis.labelpad + 15
for val, letter in [(2.8, 'a'), (11, 'b')]:
ax.annotate('${}$'.format(letter), xy=(val, 0), xytext=(0, -labelpad),
xycoords=('data', 'axes fraction'), textcoords='offset points',
ha='center', va='top', size=18)