Overplot trends in matplotlib: every loop gives additional trend - python

With the code below I get three different plots, and I would like to know how to combine them so that I have three lines on one plot. I thought there is something simple as overplot instead of plot, but somehow I could't find it.
Somehow I also need to adjust the x to the "longest" dataset.
import matplotlib.pyplot as plt
big_array = [[4,5,4,5],[6,4,1],[1,2,3,4]]
for i in big_array:
x = range(len(i))
y = i
plt.plot(x, y)
plt.show()

When you call plt.show() this displays all the current figures that have been drawn and blocks the rest of the code until the figure window has been closed.
As you are in a loop of 3 iterations you code will display and block the figure at each call to show. Then when you close the window your loop will continue, creating another figure when you call plt.plot() and then displays it again when you call show.
To fix you should only call plt.show() at the end of your script:
big_array = [[4,5,4,5],[6,4,1],[1,2,3,4]]
for i in big_array:
x = range(len(i))
y = i
plt.plot(x, y)
plt.show()
Which will produce the following figure:

Related

Matplotlib | Python | Plotting figure A and then plotting another figure B on top of figure A

The fragment of code below plots a figure based on two arrays of floats
plt.scatter(t, h)
plt.xlabel("time")
plt.ylabel("height")
plt.show()
Then, after defining a function y(t), I need to add the following on top of the last plot:
plt.plot(t, y(t), 'r')
plt.show()
However, the code above generates two separate plots. I've noticed that if I comment out the first plt.show(), I'll get the second figure I am looking for. But is there a way to show them both?
I was expecting one plot and then another plot on top of the second one; however the second plot is shown as a new one
plt.show() draws your figure on screen.
So, you need to remove the first plt.show() from your code.
If you remove the first plt.show() you should see the joint plot. The first plt.scatter just produces points on the joints of the line.
import numpy as np
import matplotlib.pyplot as plt
t = np.random.random(10)
h = np.random.random(10)
plt.scatter(t, h)
plt.plot(t, h, 'r')
plt.show()
The scatter plot is just the blue dots

Blank figure in while loop

I'm having trouble plotting graphs in a while loop (I get a blank figure that doesn't show any graph), what am I missing here? I provided an MWE that I run on Windows 10, Python 3. But I don't think the configuration is the problem:
import matplotlib.pyplot as plt
import time
def refresh(x,y1,y2,y3):
plt.close('all')
plt.figure()
plt.subplot(3,1,1)
plt.plot(x, y1)
plt.subplot(3,1,2)
plt.plot(x, y2)
plt.subplot(3,1,3)
plt.plot(x, y3)
plt.show
return
plt.ion
A = [1,2,3,4]
B = [15,16,8,2]
C = [8,6,4,7]
D = [5,4,3,1]
while True:
time.sleep(5)
refresh(A,B,C,D)
Another problem is it doesn't create a figure window, but displays the data after execution in the console. I would like it to create a figure window displaying the curves "refreshed" every 5 seconds.
If that is indeed a copy of your code, you need to actually call
plt.show()
Without the parentheses indicating a call of the function,
plt.show
just returns it being a function without actually being executed.

Matplotlib: plotting on old plot

After review this question (How do I tell Matplotlib to create a second (new) plot, then later plot on the old one?) I thought I had figured this out, but I think I'm running into an issue with my for loops. Here is a pared down version of what I'm doing.
import matplotlib.pyplot as plt
import numpy as np
for m in range(2):
x=np.arange(5)
y=np.exp(m*x)
plt.figure(1)
plt.plot(x, y)
plt.show()
...
z=np.sin(x+(m*math.pi))
plt.figure(2)
plt.plot(x,z)
...
plt.figure(2)
plt.show()
My hope was that this would display three plots: a plot for e^(0) vs x the first time through, a plot of e^x vs x the second time through, and then one plot with both sin(x) and sin(x+pi) vs x.
But instead I get the first two plots and a plot with just sin(x) and plot with just sin(x+pi).
How do I get all the data I want on to figure 2? It seems to be some sort of issue with the set figure resetting when I return to the beginning of the loop.
This minimal change will probably do what you want (although it is not the best code).
Replace plt.figure(1) with plt.figure(). Remove any plt.show() from inside the loop.
The loop will end and then all 3 figures will be shown. The e^x curves will be in figures #1 and #3.

Manage and accumulate subplots in matplotlib

I have a function that produces triangles and quadrilaterals (called 'trisq') in red or green, resp. My goal is to make an arrangement of these shapes on the same plot by running a loop over my drawing function.
I can draw multiple shapes and call plt.show() on it which works fine but after that I won't be able to add more shapes as it gives me a blank output.
I think my issue is that I don't know how to control subplot command. Please see my inline comment in the code for how it goes wrong. What would be the cleanest way to do this? Thanks!
(Btw, this is my first time posting here. I think my question is basic but I hope that at least I've posed it in a clear way).
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
fig, ax = plt.subplots()
def trisq(points):
inf = 20
plt.xlim(-inf, inf)
plt.ylim(-inf, inf)
plt.gca().set_aspect('equal', adjustable='box')
ver = np.array(points)
polygon = Polygon(ver, True)
patches = []
patches.append(polygon)
if len(points) == 3:
color = 'red'
elif len(points) == 4:
color = 'green'
p = PatchCollection(patches, color = color,cmap=matplotlib.cm.jet, alpha=0.4)
ax.add_collection(p)
trisq([(4,18),(6,16),(5,-1),(-5,9)]
trisq([(4,-8),(1,7),(15,9)])
# this works as expected
plt.show()
trisq([(4,8),(12,3),(0,0),(1,9)])
# but this one returns a blank plot
plt.show()
Update:
My concrete question is: how do I show a graph, then add more elements to it and show it again in the above context and possibly repeat inside a loop? Apparently, plt.show() can only be called once and not in an ongoing manner.
Plt.show() shows the active figures. After your first call to plt.show() there is no active figure any more.
Unfortunately the question is not clear about what the actual goal is.
You may call plt.show only once at the end. You may also create a new figure in between.
Make sure to add the collection inside the trisq function.

Plotting a continuous stream of data with MatPlotLib

I want to use MatPlotLib to plot a graph, where the plot changes over time. At every time step, an additional data point will be added to the plot. However, there should only be one graph displayed, whose appearance evolves over time.
In my test example, the plot is a simple linear plot (y = x). Here is what I have tried:
for i in range(100):
x = range(i)
y = range(i)
plt.plot(x, y)
plt.ion()
plt.show()
time.sleep(1)
However, what happens here is that multiple windows are created, so that by the end of the loop I have 100 windows. Also, I have noticed that for the most recent window, it is just a white window, and the plot only appears on the next step.
So, my two questions are:
1) How can I change my code so that only a single window is displayed, whose contents changes over time?
2) How can I change my code so that for the most recent timestep, the plot is actually displayed on the window, rather than it only displaying a white window?
Thanks!
(1)
You can set plt.ion() at the beginning and plot all graphs to the same window. Within the loop use plt.draw() to show the graph and plt.pause(t) to make a pause. Note that t can be very small, but the command needs to be there for the animation to work on most backends.
You might want to clear the axes before plotting new content using plt.gca().cla().
import matplotlib.pyplot as plt
plt.ion()
for i in range(100):
x = range(i)
y = range(i)
# plt.gca().cla() # optionally clear axes
plt.plot(x, y)
plt.title(str(i))
plt.draw()
plt.pause(0.1)
plt.show(block=True) # block=True lets the window stay open at the end of the animation.
Alternatively to this very simple approach, use any of the examples for animations provided in http://matplotlib.org/examples/animation/index.html
(2)
In order to get each plot in a new window, use plt.figure() and remove plt.ion(). Also only show the windows at the end:
import matplotlib.pyplot as plt
for i in range(100):
x = range(i)
y = range(i)
plt.figure()
plt.plot(x, y)
plt.title(str(i))
plt.show()
Note that you might find that in both cases the first plot is empty simply because for i=0, range(i) == [] is an empty list without any points. Even for i=1 there is only one point being plotted, but of course no line can connect a single point with itself.
I think the best way is to create one line plot and then update data in it. Then you will have single window and single graph that will continuously update.
import matplotlib.pyplot as plt
plt.ion()
fig = plt.figure(figsize=(16,8))
axes = fig.add_subplot(111)
data_plot=plt.plot(0,0)
line, = axes.plot([],[])
for i in range(100):
x = range(i)
y = range(i)
line.set_ydata(y)
line.set_xdata(x)
if len(y)>0:
axes.set_ylim(min(y),max(y)+1) # +1 to avoid singular transformation warning
axes.set_xlim(min(x),max(x)+1)
plt.title(str(i))
plt.draw()
plt.pause(0.1)
plt.show(block=True)

Categories

Resources