Matplotlib FuncAnimation not plotting x-axis in order

779 views Asked by At

I'm trying to grab data from a text file and plot it using the animation.FuncAnimation module from matplotlib. Here is my code that I'm trying to make run correctly

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style

style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

def animate(i):
    graph_data = open('example.txt', 'r').read()
    lines = graph_data.split('\n')
    xs = []
    ys = []

    for line in lines:
        x,y = line.split(',')
        xs.append(x)
        ys.append(y)

    ax1.clear()
    ax1.plot(xs, ys)

animation.FuncAnimation(fig, animate, interval=1000)
plt.show()

example.txt is an 18-line text file (omitted for space reasons) which contain (x,y) pairs of data which I'd like to plot. However, matplotlib is not plotting the x values in order: once they reach 10, they 'wrap around' back to the beginning, sandwiching themselves between 1 and 2. Makes for a pretty bad graph.

I'm having some trouble figuring out what's wrong with my implementation. I've even tried sorting the values before plotting them, but the plot still comes out like this.

All help is appreciated! I've been scouring doc pages and StackOverflow for a while now, and I can't seem to find anyone whose had this same problem.

2

There are 2 answers

1
Raj Roy On

The numbers are not in order because you are treating them as strings not numbers. So append them as floats and it will solve it. Try:

xs.append(float(x))
ys.append(float(y))
3
Dawid Laszuk On

Quick answer: Working example below.

There are few aspects you should be aware of. Firstly, FuncAnimation will execute animate function on each call, i.e. every interval milliseconds, which in your case is 1 second. You don't really want to read file again and again... do it once before and then update your view. Secondly, creating each time whole axis (ax.plot) is very expensive and it'll slow down quickly.

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style


graph_data = open('example.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []

for line in lines[:-1]:
    x,y = line.split(',')
    xs.append(float(x))
    ys.append(float(y))

# This is where you want to sort your data
# sort(x, y, reference=x) # no such function

style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

x, y = [], [] # Prepare placeholders for animated data
ln, = plt.plot(x, y, animated=True)
ax1.set_xlim(min(xs), max(xs)) # Set xlim in advance
ax1.set_ylim(min(ys), max(ys)) #     ylim

def animate(i):
    x.append(xs[i])
    y.append(ys[i])
    ln.set_data(x, y)
    return ln,

ani = animation.FuncAnimation(fig, animate, frames=range(len(xs)),  
                                interval=1000, repeat=False, blit=True)
plt.show()

Notice that we used repeat flag to False. This means that once it goes through whole frames list then it stops.