Plotting y-values in pyplot is easy, given a list of y_values = [0, 1, 4, 9], pyplot automatically plots this using
plt.plot(y_values)
plt.show()
As pyplot automatically enumerates these using [0,1,2,3]. However, given a list of x_values, is there a way to automatically plot these without providing y-values? e.g. let pyplot automatically enumerating them?
I've tried
plt.plot(x=x_values); plt.plot(xdata=x_values)
However none of these seem to work. Of course, one way would be to flip the axes, but is there a simpler way I've overlooked?
The x and y arguments in pyplot.plot(*args, **kwargs) are positional arguments. According to the documentation, e.g.
plot(x, y) # plot x and y using default line style and color
plot(x, y, 'bo') # plot x and y using blue circle markers
plot(y) # plot y using x as index array 0..N-1
Now, how would pyplot know that if you specify a single argument, you would want it to be interpreted as the ordinate instead of the coordinate? It's simply not possible the way the function is written.
A solution to plot the index against some list is to supply the index as y argument:
import matplotlib.pyplot as plt
x_values = [0, 1, 4, 9]
plt.plot(x_values, range(len(x_values)))
plt.show()
Related
I have a boolean time series that I want to use to determine the parts of the plot that should be shaded.
Currently I have:
ax1.fill_between(data.index, r_min, r_max, where=data['USREC']==True, alpha=0.2)
where, r_min and r_max are just the min and max of the y-axis.
But the fill_between doesn't fill all the way to the top and bottom of the plot because, so I wanted to use axvspan() instead.
Is there any easy way to do this given axvspan only takes coordinates? So the only way I can think of is to group all the dates that are next to each other and are True, then take the first and last of those dates and pass them into axvspan.
Thank you
You can still use fill_between, if you like. However instead of specifying the y-coordinates in data coordinates (for which it is not a priori clear, how large they need to be) you can specify them in axes coorinates. This can be achieved using a transform, where the x part is in data coordinates and the y part is in axes coordinates. The xaxis transform is such a transform. (This is not very surprising since the xaxis is always independent of the ycoorinates.) So
ax.fill_between(data.index, 0,1, where=data['USREC'], transform=ax.get_xaxis_transform())
would do the job.
Here is a complete example:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(0)
x = np.linspace(0,100,350)
y = np.cumsum(np.random.normal(size=len(x)))
bo = np.zeros(len(y))
bo[y>5] = 1
fig, ax = plt.subplots()
ax.fill_between(x, 0, 1, where=bo, alpha=0.4, transform=ax.get_xaxis_transform())
plt.plot(x,y)
plt.show()
I have a function wrapper for making a plot in matplotlib. i want to know how best we return the figure handle from inside the function. I want to use the figure handle to update the plot by putting more points on it. The size of the points should depend on it's value of the data point. The bigger the data point, the bigger the size of the point.
One common way is to return an Axes object from your function. You can do additional plotting directly from the Axes.
You don't say whether your function is using the pyplot state machine or bare-bones Matplotlib, but here's an example of the former:
import matplotlib.pyplot as plt
x = range(3)
y1 = [2, 1, 3]
y2 = [3, 2, 1]
def plot_data(x, y):
"""Plots x, y. Returns the Axes."""
plt.plot(x, y, '-.k')
return plt.gca()
ax = plot_data(x, y1)
ax.scatter(x, y2, s=y2)
Here we also use the s= argument to specify the size of each point. Matplotlib assumes certain units for these values so you may end up having to multiply by some constant to scale them to meet your aesthetics.
Note that in addition to returning the Axes, sometimes it's useful to also have your plotting function also take an existing Axes as the argument.
I'm plotting a vector field with the quiver method of Matplotlib.
My array to store this vector has a dimension x * y but I'm working with a space that varies from -2 to 2.
So far, to plot the vector field I have this method:
import matplotlib.pyplot as plt
def plot_quiver(vector_field_x, vector_field_y, file_path):
plt.figure()
plt.subplots()
plt.quiver(vector_field_x, vector_field_y)
plt.savefig(file_path + '.png')
plt.close()
Which gives me this output, as an example, for a 10 x 10 array:
But to generate this vector field I centered my data in the x = 0, y = 0, x and y ranging from -2 to 2.
Then, I would like to plot the axis of the image following this pattern.
As an standard approach, I tried to do the following:
def plot_quiver(vector_field_x, vector_field_y, file_path):
plt.figure()
fig, ax = plt.subplots()
ax.quiver(vector_field_x, vector_field_y)
ax.set_xticks([-2, 0, 2])
ax.set_yticks([-2, 0, 2])
plt.savefig(file_path + '.png')
plt.close()
Which usually works with Matplotlib methods, as imshow and streamplot, for example.
But this what I've got with this code:
Which is not what I want.
So, I'm wondering how can I perform what I explained here to change the axes ticks.
Thank you in advance.
Funny thing, I just learnt about quiver yesterday... :)
According to the quiver documentation, the function can accept from 2 to 5 arguments...
The simplest way to use the function is to pass it two arrays with equal number of elements U and V. Then, matplotlib will plot an arrow for each element in the arrays. Specifically, for each element i,j you will get an arrow placed at i,j and with components defined by U[i,j] and V[i,j]. This is what is happening to you
A more complete syntax is to pass our arrays with equal number of elements X, Y, U and V. Again, you will get an arrow for each i,j element with components defined by U[i,j] and V[i,j], but this time they will be placed at coordinates X[i,j], Y[i,j].
In conclusion:
you need to call quiver like
quiver(values_x, values_y, vector_field_x, vector_field_y)
Probably you already did it, but you can get values_x and values_y using the numpy.meshgrid function.
The matplotlib example for the quiver function might be useful, also.
I hope it helps!
I'm trying to make a simple 2d plot from a 3 column data sets e.g. y=f(x) and z=f(x). I want to plot xy and would like to display z using color. For example, the rectangular regions between [x1,x2, min(y), max(y)] ... will be filled by a background color depending on the value of z. I tried to use fill_between but could not associate a colormap with it. I'm new to matplotlib and python. I would very much appreciate your comments/suggestions.
Edit: I don't have an accurate plot but I'll try to explain my query with the help of following figure sample plot
say between x=0.5 to x=1, z=1
x=1.0, to x=1.5, z=2 ....
so I would like to cover x=0.5 to x=1 (min(y) to max(y)] with some color that corresponds to z=1, and between x=1, x=1.5, z=2 and so on.. I want to show this variation using a colormap and to display this colorbar at the right side.
Here's the solution those who want cannot use contourf or need fill_between for some other reason (as in this case with irregular grid data).
import numpy as np
import matplotlib.pyplot as plt
from random import randint, sample
import matplotlib.colorbar as cbar
# from Numeric import asarray
%matplotlib inline
# The edges of 2d grid
# Some x column has varying rows of y (but always the same number of rows)
# z array that corresponds a value in each xy cell
xedges = np.sort(sample(range(1, 9), 6))
yedges = np.array([np.sort(sample(range(1, 9), 6)) for i in range(5)])
z = np.random.random((5,5))
f, ax = plt.subplots(1, sharex=True, figsize=(8,8))
f.subplots_adjust(hspace=0)
ax.set_ylabel(r'y')
ax.set_xlabel(r'x')
ax.set_ylim(0,10)
ax.set_xlim(0,10)
c = ['r','g','b','y','m']
normal = plt.Normalize(z.min(), z.max())
cmap = plt.cm.jet(normal(z))
# plot showing bins, coloured arbitrarily.
# I want each cell coloured according to z.
for i in range(len(xedges)-1):
for j in range(len(yedges)):
ax.vlines(xedges[i],yedges[i][j],yedges[i][j+1],linestyle='-')
ax.hlines(yedges[i][j],xedges[i],xedges[i+1],linestyle='-')
ax.vlines(xedges[i+1],yedges[i][j],yedges[i][j+1],linestyle='-')
ax.hlines(yedges[i][j+1],xedges[i],xedges[i+1],linestyle='-')
ax.fill_between([xedges[i],xedges[i+1]],yedges[i][j],yedges[i][j+1],facecolor=cmap[i][j][:])
cax, _ = cbar.make_axes(ax)
cb2 = cbar.ColorbarBase(cax, cmap=plt.cm.jet,norm=normal)
This gives
It sound to me like you should use contourf
http://matplotlib.org/examples/pylab_examples/contourf_demo.html
This would take x as some dependant variable, produce y = y(x) and z = z(x). It seems that your z is not dependant on y but contourf can still handle this.
As a simple example:
import pylab as plt
x = plt.linspace(0,2,100)
y = plt.linspace(0,10,100)
z = [[plt.sinc(i) for i in x] for j in y]
CS = plt.contourf(x, y, z, 20, # \[-1, -0.1, 0, 0.1\],
cmap=plt.cm.rainbow)
plt.colorbar(CS)
plt.plot(x,2+plt.sin(y), "--k")
The are many variations but hopefully this captures the elements you are looking for
I want to make a scatterplot (using matplotlib) where the points are shaded according to a third variable. I've got very close with this:
plt.scatter(w, M, c=p, marker='s')
where w and M are the data points and p is the variable I want to shade with respect to.
However I want to do it in greyscale rather than colour. Can anyone help?
There's no need to manually set the colors. Instead, specify a grayscale colormap...
import numpy as np
import matplotlib.pyplot as plt
# Generate data...
x = np.random.random(10)
y = np.random.random(10)
# Plot...
plt.scatter(x, y, c=y, s=500) # s is a size of marker
plt.gray()
plt.show()
Or, if you'd prefer a wider range of colormaps, you can also specify the cmap kwarg to scatter. To use the reversed version of any of these, just specify the "_r" version of any of them. E.g. gray_r instead of gray. There are several different grayscale colormaps pre-made (e.g. gray, gist_yarg, binary, etc).
import matplotlib.pyplot as plt
import numpy as np
# Generate data...
x = np.random.random(10)
y = np.random.random(10)
plt.scatter(x, y, c=y, s=500, cmap='gray')
plt.show()
In matplotlib grey colors can be given as a string of a numerical value between 0-1.
For example c = '0.1'
Then you can convert your third variable in a value inside this range and to use it to color your points.
In the following example I used the y position of the point as the value that determines the color:
from matplotlib import pyplot as plt
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
y = [125, 32, 54, 253, 67, 87, 233, 56, 67]
color = [str(item/255.) for item in y]
plt.scatter(x, y, s=500, c=color)
plt.show()
Sometimes you may need to plot color precisely based on the x-value case. For example, you may have a dataframe with 3 types of variables and some data points. And you want to do following,
Plot points corresponding to Physical variable 'A' in RED.
Plot points corresponding to Physical variable 'B' in BLUE.
Plot points corresponding to Physical variable 'C' in GREEN.
In this case, you may have to write to short function to map the x-values to corresponding color names as a list and then pass on that list to the plt.scatter command.
x=['A','B','B','C','A','B']
y=[15,30,25,18,22,13]
# Function to map the colors as a list from the input list of x variables
def pltcolor(lst):
cols=[]
for l in lst:
if l=='A':
cols.append('red')
elif l=='B':
cols.append('blue')
else:
cols.append('green')
return cols
# Create the colors list using the function above
cols=pltcolor(x)
plt.scatter(x=x,y=y,s=500,c=cols) #Pass on the list created by the function here
plt.grid(True)
plt.show()
A pretty straightforward solution is also this one:
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8,8))
p = ax.scatter(x, y, c=y, cmap='cmo.deep')
fig.colorbar(p,ax=ax,orientation='vertical',label='labelname')