Is there a simple way to animate a scatterplot in matplotlib, in a similar way to which the plot is created?
I know currently I can do this to create the plot:
scatter = ax.scatter([x values], [y values], [z values])
However, every example I find online uses numpy functions to generate its data rather than something external like three lists, leaving me with much difficulty understanding how the data is modified in the method which updates the animation.
Is it possible to give matplotlib an entirely new set of data to plot for each frame? (every point of data will change anyway)
Note: in case there are special considerations for this situation, this is a 3D plot.
The easiest way to animate is to plot in interactive mode, as a minimal(ish) examples with lists,
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.show()
for i in range(1000):
x =[1,2,3,4,5,6,7,8,9,10]
y =[5,6+i%10,2,3,13,4,1,2,4-i%10,8]
z =[2+(i%10)*2.,3,3,3,5,7,9+i%10,11,9+i%10,10]
ax.scatter(x, y, z, marker='o')
ax.set_xlim([0.,10.])
ax.set_ylim([0.,20.])
ax.set_zlim([0.,20.])
plt.pause(0.01)
plt.cla()
A reason to plot using numpy arrays instead of lists is the data is stored as a contiguous block and this speeds up plots (it's easy to convert to an array with xn = np.array(x)). The main reason most examples will use various numpy functions is that it is just easier to provide a self contained demonstration with animation in matplotlib requiring a function which adjusts the collection object. For a great example of a minimum scatter plot animation, see the second example of this.
Related
I've been using Python/NumPy for a lot of things for a while now, but I am still confused about creating 3D plots.
In a "traditional" data analysis program (Origin, SigmaPlot, Excel...), if you want to make a 3D plot or a contour plot, you usually have your data in (X,Y,Z) format, that is, for each pair of X and Y you have one value of Z.
As opposed to this, all Python plotting guides I find use numpy.meshgrid for plotting -and I don't fully understand the connection to the traditional plotting software.
Let's say I have the following code:
axes_range = np.linspace(-5, 5, num=25)
alphas = []
for xcoord in axes_range:
for ycoord in axes_range:
alphas.append(f(xcoord,ycoord))
What's the best way of making a plot of (xcoord, ycoord, alphas)?
With matplotlib you simply need
import matplotlib.pylab as plt
import numpy as np
from matplotlib import cm
X, Y = np.meshgrid(xcoord, ycoord)
plt.contourf(X, Y, alphas.T, levels=20, cmap=cm.jet)
plt.show()
I think you need to transpose alphas as I do here.
This question already has answers here:
Removing axes margins in 3D plot
(2 answers)
Closed 4 years ago.
I'm having an issue with setting limits for my 3d plots in matplotlib; I'm finding that no matter how I set my limits for the x,y, and z axes, the plotting routine for 3dplots adds an extra buffer.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.axes.set_xlim3d(left=0, right=10)
ax.axes.set_ylim3d(bottom=0, top=10)
ax.axes.set_zlim3d(bottom=0, top=10)
plt.show()
This produces the following plot:
As you can see, the limits are supposed to be at x, y, z = {0, 10} however the 3D plotting always adds a little bit of a buffer to each edge. Does anyone know a way to turn this effect off?
I've also used plt.xlims(); and ax.axes.set_xlims() but they produce the same effect.
I think this is deliberate (see e.g. this), if you try plotting ax.axes.set_xlim3d(left=0.000001, right=9.9999999) then you get no 0 or 10 displayed on your figure.
Even making the numbers as arbitrarily close as possible doesn't work, e.g.
eps = 1e-16
ax.axes.set_xlim3d(left=0.-eps, right=10+eps)
ax.axes.set_ylim3d(bottom=0.-eps, top=10+eps)
ax.axes.set_zlim3d(bottom=0.-eps, top=10+eps)
The best solution I've found is to set the ticks manually and then slightly scale so the overlap is hidden.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.set_xticks([0,2,4,6,8,10])
ax.set_yticks([0,2,4,6,8,10])
ax.set_zticks([0,2,4,6,8,10])
ax.axes.set_xlim3d(left=0.2, right=9.8)
ax.axes.set_ylim3d(bottom=0.2, top=9.8)
ax.axes.set_zlim3d(bottom=0.2, top=9.8)
plt.show()
This gives,
This is pretty hacky but could be made more general (and I always end up setting ticks manually for publication quality figures). Alternatively, it may be better to turn off the lowest grid line or hide the grid...
I'm kind of confused what is going at the backend when I draw plots in matplotlib, tbh, I'm not clear with the hierarchy of plot, axes and figure. I read the documentation and it was helpful but I'm still confused...
The below code draws the same plot in three different ways -
#creating the arrays for testing
x = np.arange(1, 100)
y = np.sqrt(x)
#1st way
plt.plot(x, y)
#2nd way
ax = plt.subplot()
ax.plot(x, y)
#3rd way
figure = plt.figure()
new_plot = figure.add_subplot(111)
new_plot.plot(x, y)
Now my question is -
What is the difference between all the three, I mean what is going under the hood when any of the 3 methods are called?
Which method should be used when and what are the pros and cons of using any on those?
The names of objects
Matplotlib is strongly object oriented and its principal objects are the figure and the axes (I find the name axes a bit misleading, but probably it's just me).
You can think of the figure as a canvas, of which you typically specify the dimensions and possibly e.g., the background color etc etc. You use the canvas, the figure, essentially in two ways, placing other objects on it (mostly axes, but also text labels etc) and saving its contents with savefig.
You can think of an axes as a sort of Swiss Army knife, a handy object that offers a tool (e.g. .plot, .scatter, .hist etc) for everything, mostly. You can place one, two, ... many axes inside a figure using one of many different methods.
The plt interface
The plt procedural interface was originally developed to mimic the MATLAB™ interface but is not really different from the object oriented interface, even if you don't make a direct reference to the main objects (i.e., a figure and an axes) these objects are automatically instantiated and each plt method is, essentially, translated to a call of one of the methods of the underlying fundamental objects: e.g., a plt.plot() is a hidden_axes.plot and a plt.savefig is a hidden_figure.savefig.
In every moment you can have an handle on these hidden objects using plt.gcf and plt.gca, and this is sometimes necessary when one of the object methods has not been ported to a method in the plt namespace.
I'd like to add that the plt namespace contains also a number of convenience methods¹ to instantiate, in different ways, figure and axes.
Your examples
1st way
plt.plot(x, y)
Here you use only the plt interface, you can only use a single axes in each figure, but this is what you want when you are doing an exploration of your data,
a quick recipe that gets the work done...
2nd way
ax = plt.subplot()
ax.plot(x, y)
Here you use a convenience method in the plt namespace to give a name (and a handle) to your axes object, but btw there is also an hidden figure. You can later use the axes object to plot, to make an histogram etc, all things that you can do with the plt interface, but you can also access all its attributes and modify them with greater freedom.
3rd way
figure = plt.figure()
new_plot = figure.add_subplot(111)
new_plot.plot(x, y)
Here you start instantiating a figure using a convenience method in the plt namespace and later you use only the object oriented interface.
It is possible to bypass the plt convenience method (matplotlib.figure.Figure) but you then have to tweak the figure for a better interactive experience (after all, it's a convenience method).
Personal recommendations
I suggest bare plt.plot, plt.scatter in the context of an interactive session, possibly using IPython with its %matplotlib magic command, and also in the context of an exploratory Jupyter notebook.
On the other hand the object oriented approach, plus a few plt
convenience methods¹, is the way to go
if you have a permanent issue to solve once for all with a
customized arrangement of finely tuned subplots,
if you want to embed Matplotlib in the UI of a program you write.
There is a large gray area between these extremes and if you ask me what to do I'd just say "It depends"...
(1) The convenience methods in the plt name space are REALLY CONVENIENT! In particular, when you instantiate Figures and Axes using them, all the minute details needed to deal with interactive windows are automatically taken into account.
Method 1
plt.plot(x, y)
This lets you plot just one figure with (x,y) coordinates. If you just want to get one graphic, you can use this way.
Method 2
ax = plt.subplot()
ax.plot(x, y)
This lets you plot one or several figure(s) in the same window. As you write it, you will plot just one figure, but you can make something like this:
fig1, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
You will plot 4 figures which are named ax1, ax2, ax3 and ax4 each one but on the same window. This window will be just divided in 4 parts with my example.
Method 3
fig = plt.figure()
new_plot = fig.add_subplot(111)
new_plot.plot(x, y)
I didn't use it, but you can find documentation.
Example:
import numpy as np
import matplotlib.pyplot as plt
# Method 1 #
x = np.random.rand(10)
y = np.random.rand(10)
figure1 = plt.plot(x,y)
# Method 2 #
x1 = np.random.rand(10)
x2 = np.random.rand(10)
x3 = np.random.rand(10)
x4 = np.random.rand(10)
y1 = np.random.rand(10)
y2 = np.random.rand(10)
y3 = np.random.rand(10)
y4 = np.random.rand(10)
figure2, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
ax1.plot(x1,y1)
ax2.plot(x2,y2)
ax3.plot(x3,y3)
ax4.plot(x4,y4)
plt.show()
Other example:
Due to the 2nd answer of this question I supposed the following code
import matplotlib.pyplot as plt
for i1 in range(2):
plt.figure(1)
f, ax = plt.subplots()
plt.plot((0,3), (2, 2), 'b')
for i2 in range(2):
plt.figure(2)
f, ax = plt.subplots()
plt.plot([1,2,3], [1,2,3], 'r')
plt.savefig('foo_{}_bar_{}.jpg'.format(i2, i1))
plt.close()
plt.figure(1)
plt.plot( [1,2,3],[1,2,3], 'r')
plt.savefig('bar_{}.jpg'.format(i1))
plt.close()
to create plots bar_0.jpg and bar_1.jpg showing a blue and a red line each.
However, figures look like
instead of
How can I achieve the desired behaviour?
Note that plots foo_*.jpg have to be closed and saved during handling of the bar plots.
You're already saving the Axes objects, so instead of calling the PyPlot plot function (which draws on the last created or activated Axes), use the objects' plot function:
ax.plot(...)
If you then give both a different name, say ax1 and ax2, you can draw on the one you like without interfering with the other. All plt. commands also exist as an Axes member function, but sometimes the name changes (plt.xticks becomes ax.set_xticks for example). See the documentation of Axes for details.
To save to figures, use the Figure objects in the same way:
f.savefig(...)
This API type is only just coming to Matlab, FYI, and will probably replace the old-fashioned "draw on the last active plot" behaviour in the future. The object-oriented approach here is more flexible with minimal overhead, so I strongly recommend you use it everywhere.
If unsure, better to make it explicit:
import matplotlib.pyplot as plt
for i1 in range(2):
fig1,ax1 = plt.subplots()
fig2,ax2 = plt.subplots()
ax1.plot([0,4],[2,2],'b')
for i2 in range(2):
ax2.plot([1,2,3],[1,2,3],'r')
fig2.savefig('abc{}.png'.format(2*i1+i2))
plt.figure(1)
ax1.plot([1,2,3],[1,2,3],'r')
fig1.savefig('cba{}.png'.format(i1))
I have a data set that has two independent variables and 1 dependent variable. I thought the best way to represent the dataset is by a checkerboard-type plot wherein the color of the cells represent a range of values, like this:
I can't seem to find a code to do this automatically.
You need to use a plotting package to do this. For example, with matplotlib:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
X = 100*np.random.rand(6,6)
fig, ax = plt.subplots()
i = ax.imshow(X, cmap=cm.jet, interpolation='nearest')
fig.colorbar(i)
plt.show()
For those who come across this years later as myself, what Original Poster wants is a heatmap.
Matplotlib has documentation regarding the following example here.