1

This might be obvious, so sorry in advance for this nooby question. I want to update a time series dynamically with matplotlib.pyplot. More precisely, I want to plot newly generated data in a while-loop.

This is my attempt so far:

import numpy as np
import matplotlib.pyplot as plt; plt.ion()
import pandas as pd
import time

n = 100
x = np.NaN
y = np.NaN
df = pd.DataFrame(dict(time=x, value=y), index=np.arange(n)) # not neccessarily needed to have a pandas df here, but I like working with it.

# initialise plot and line
line, = plt.plot(df['time'], df['value'])
i=0

# simulate line drawing
while i <= len(df):

    #generate random data point
    newData = np.random.rand()

    # extend the data frame by this data point and attach the current time as index
    df.loc[i, "value"] = newData
    df.loc[i, "time"] = pd.datetime.now()

    # plot values against indices
    line.set_data(df['time'][:i], df['value'][:i])
    plt.draw()

    plt.pause(0.001)

    # add to iteration counter
    i += 1

    print(i)

This returns TypeError: float() argument must be a string or a number, not 'datetime.datetime'. But as far as I can remeber, matplotlib doesn't have any problems with plotting dates on the x-axis (?).

Many thanks.

1

1 Answer 1

2

As Andras Deak pointed out, you should tell pandas explicitly that your time column is datetime. When you do df.info() at the end of your code, you will see that it takes df['time'] as float64. You can achieve this with df['time'] = pd.to_datetime(df['time']).

I was able to make your code run, but I had to add a few lines of code. I was running it in a iPython (Jupyter) console and without the two lines autoscale_view and relim, it was not updating the plot correctly. What's left to do is a nice formatting of the x-axis labels.

import numpy as np
import matplotlib.pyplot as plt; plt.ion()
import pandas as pd
import time

n = 100
x = np.NaN
y = np.NaN
df = pd.DataFrame(dict(time=x, value=y), index=np.arange(n)) # not neccessarily needed to have a pandas df here, but I like working with it.
df['time'] = pd.to_datetime(df['time']) #format 'time' as datetime object

# initialise plot and line
fig = plt.figure()
axes = fig.add_subplot(111)
line, = plt.plot(df['time'], df['value'])

i=0

# simulate line drawing
while i <= len(df):    
    #generate random data point
    newData = np.random.rand()

    # extend the data frame by this data point and attach the current time as index
    df.loc[i, "value"] = newData
    df.loc[i, "time"] = pd.datetime.now()

    # plot values against indices, use autoscale_view and relim to readjust the axes
    line.set_data(df['time'][:i], df['value'][:i])
    axes.autoscale_view(True,True,True)
    axes.relim()
    plt.draw()

    plt.pause(0.01)

    # add to iteration counter
    i += 1

    print(i)
Sign up to request clarification or add additional context in comments.

3 Comments

Beautiful. Thanks!
May I ask you to edit your example such that the x axis correctly displays the datetime?
I tried but I was struggling. Somehow, the usual way with set_major_formatter using matplotlib.dates doesn't work with the time format of the pandas dataframe, and when I use a float-dataframe, it results in your float-error again. I can maybe try again tomorrow, but if you can not figure it out yourself, it would be probably best to create a new question since this one is already accepted (although people might just refer you to "matplotlib animation").

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.