2

How can I have the line plot, with the data coming one by one? I have the code

import matplotlib.pyplot as plt

plt.ion()
plt.plot(1, 2)
plt.pause(2.5)
plt.plot(2, 5)
plt.pause(2.5)

but it does not show the line, if I add 'o' option in plot function or change the plot function to scatter function, it works fine, But I want a line with no markers, how can I do this?

  • 1
    Your example creates, with your two `plot` calls, two "lines" with a single point each, so if you don't have any markers, it's invisible to the eye. Add your data to lists for x and y instead and plot those. – Dominik Stańczak Jul 10 '22 at 13:17
  • Please ask one question at a time. – Matt Hall Jul 10 '22 at 13:28
  • @DominikStańczak If so, should I delete the current plot and plot a new one each time I want to update the plot? – Jiang Yuanhao Jul 10 '22 at 14:06
  • Does this answer your question? [Animating "growing" line plot in Python/Matplotlib](https://stackoverflow.com/questions/28074461/animating-growing-line-plot-in-python-matplotlib) – Dominik Stańczak Jul 10 '22 at 16:01

2 Answers2

3

I tried the following code, according with my tests it works only if the plot is generated in an external window:

import matplotlib.pyplot as plt

plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.grid(True)

x = [4, 1, 5, 3, 8]
y = [1, 2, 9, 0, 2]

ax.set_xlim(0, 9)
ax.set_ylim(-1, 10)

for j in range(1, len(x)):
     X = [x[j-1], x[j]]
     Y = [y[j-1], y[j]]
     ax = plt.plot(X, Y, mew = 5, ms = 5)
     # mew and ms used to change crosses size
     plt.pause(1)# one second of delay
     plt.show()     

If you are working on Spyder, in order to make the intepreter generating an external window whenever you call a plot you have to type

%matplotlib qt

on the intepreter (and not into the script file!) BEFORE running the previous lines of code

Stefano Fedele
  • 6,877
  • 9
  • 29
  • 48
3

To respond to the comment about "deleting the current plot", and to improve upon Stefano's answer a bit, we can use Matplotlib's object-oriented interface to do this:

import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5, 6]
y = [3, 1, 4, 1, 5, 9, 2]

fig, ax = plt.subplots()
ax.set(xlim=(min(x), max(x)), ylim=(min(y), max(y)))

plt.ion()

(line,) = ax.plot([], [])  # initially an empty line

timestep = 0.5  # in seconds

for i in range(1, len(x) + 1):
    line.set_data(x[:i], y[:i])
    plt.pause(timestep)
plt.show(block=True)

This version uses a single Line2D object and modifies its underlying data via set_data. Since Matplotlib doesn't have to draw multiple objects, just the one line, it should scale better once your data becomes large.

Dominik Stańczak
  • 2,046
  • 15
  • 27
  • Thanks! Instead of using `ax.set()` at start, I won't have the data at start, it comes one by one, so can it change the limit of x and y axis dynamically, instead of call `ax.set()` each time a data comes? (if I use scatter() it just expend the limit automatically if needed, can this be like that?) – Jiang Yuanhao Jul 12 '22 at 17:44
  • 1
    It's not THAT smart :D but you can keep track of the min-max info for both axes yourself, pretty efficiently too (without looping, as you're just comparing old min/max and new value) and call ax.set again within the data loop only if the min/max changes. – Dominik Stańczak Jul 13 '22 at 04:40