Coolcrab
Coolcrab

Reputation: 2723

Python Use data/time as x-axis?

I'm playing around with my raspberry pi sensors and trying to make a decent plot of the readings. Now I am savind all the data into a google docs: https://docs.google.com/spreadsheet/ccc?key=0AqwhQwJogqG0dDBiU1RuNzlKM1V5OXB3dkRPamctbnc#gid=0 And using both data+time and a unix timestamp to save the time.

Plotting with the unix time works perfectly

graph

But I would like to use real time as the axis (or as a subaxis) But I can't seem to read it in nor plot it.

import numpy as np
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt

#import data
data = np.loadtxt('DHT11.csv', delimiter = ',', skiprows = 1,
                     usecols = (0,2,3,4,5,6), unpack = 1)

#id, unixtime, temp, humidity, lightlevel, lightvolt

i = data[0]
time = data[1]
temp = data[2]
hum = data[3]
light_lv =  1/data[4]*1000
light_v = data[5]


if 1:

    host = host_subplot(111, axes_class=AA.Axes)
    plt.subplots_adjust(right=0.75)

    par1 = host.twinx()
    par2 = host.twinx()

    offset = 60
    new_fixed_axis = par2.get_grid_helper().new_fixed_axis
    par2.axis["right"] = new_fixed_axis(loc="right",
                                        axes=par2,
                                        offset=(offset, 0))

    par2.axis["right"].toggle(all=True)



    #host.set_xlim(0, 2)
    #host.set_ylim(0, 2)

    host.set_xlabel("Time (unix)")
    host.set_ylabel("Temperature (C)")
    par1.set_ylabel("Humidity (%)")
    par2.set_ylabel("Light (A.U.)")

    p1, = host.plot(time, temp)
    p2, = par1.plot(time, hum)
    p3, = par2.plot(time, light_lv)

    #par1.set_ylim(0, 4)
    #par2.set_ylim(1, 65)

    host.legend()

    host.axis["left"].label.set_color(p1.get_color())
    par1.axis["right"].label.set_color(p2.get_color())
    par2.axis["right"].label.set_color(p3.get_color())

    plt.draw()
    plt.show()

    #plt.savefig("Test")

Could anyone please help out?

Upvotes: 2

Views: 3129

Answers (2)

unutbu
unutbu

Reputation: 879361

You could define a custom formatter (see below), but if you do it that way you'd need to define the formatter for each axis, host, par1, par2.

I think an easier solution would be to convert your time to Python datetime.datetime objects, and let Matplotlib handle the formatting. You could still use a custom formatter if you don't like how Matplotlib formats the dates.

import datetime as DT
time = [DT.datetime.fromtimestamp(t/1000) for t in time]
...
p1, = host.plot(time, temp)
p2, = par1.plot(time, hum)
p3, = par2.plot(time, light_lv)

By the way, you can define i, time, temp, etc. directly (without using the temp variable data):

i, time, temp, hum, light_lv, light_v = np.loadtxt(
    'DHT11.csv', delimiter = ',', skiprows = 1,
    usecols = (0,2,3,4,5,6), unpack = 1)

time = [DT.datetime.fromtimestamp(t/1000) for t in time]
light_lv = 1.0/light_lv*1000

If the x-axis values are Python datetime.datetime objects, to set a custom formatter, use

import matplotlib.dates as mdates
xfmt = mdates.DateFormatter('%Y-%m-%d %H:%M:%S')
ax.xaxis.set_major_formatter(xfmt)

If the x-axis values are timestamps, use

import datetime as DT
import matplotlib.ticker as ticker
xfmt = ticker.FuncFormatter(lambda timestamp, pos: DT.fromtimestamp(x/1000.0).strftime('%Y-%m-%d'))
ax.xaxis.set_major_formatter(xfmt)

Where ax is host, par1, and/or par2.

Upvotes: 1

behzad.nouri
behzad.nouri

Reputation: 77951

If you convert your data to pandas time series, it will automatically do that for you. it will also choose appropriate label format according to frequency of the data. For example if your data come in seconds:

import pandas as pd
import numpy as np

n = 100
idx = pd.date_range( start=dt.datetime.now( ), periods=n, freq='S' )
ts1= pd.Series( np.sin( np.linspace( 0, 4 * np.pi, n ) ), index=idx)
ts2= pd.Series( np.cos( np.linspace( 0, 4 * np.pi, n ) ), index=idx)

fig = plt.figure( figsize=(8, 6) )
ax = fig.add_axes( [.05, .05, .9, .9] )

ts1.plot( ax )
ts2.plot( ax )
(ts1 - ts2).plot( ax )

you get this:

ts3

and if you have daily data:

ts= pd.Series( np.sin( np.linspace( 0, 4 * np.pi, n ) ),
               index=pd.date_range( start=dt.datetime.now( ), periods=n, freq='D' ))
ts.plot( )           

ts2

Upvotes: 0

Related Questions