Source code for openaq.viz
from .decorators import skipif
try:
import pandas as pd
_no_pandas = False
except ImportError:
_no_pandas = True
try:
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.dates as dates
_no_sns = False
except ImportError:
_no_sns = True
def tsindex(ax):
"""
Reset the axis parameters to look nice!
"""
# Get dt in days
dt = ax.get_xlim()[-1] - ax.get_xlim()[0]
if dt <= 1./24.: # less than one hour
pass
elif dt <= 1.: # less than one day
ax.xaxis.set_minor_locator( dates.HourLocator() )
ax.xaxis.set_minor_formatter( dates.DateFormatter(""))
ax.xaxis.set_major_locator( dates.HourLocator( interval=3))
ax.xaxis.set_major_formatter( dates.DateFormatter("%-I %p"))
elif dt <= 7.: # less than one week
ax.xaxis.set_minor_locator( dates.DayLocator())
ax.xaxis.set_minor_formatter( dates.DateFormatter("%d"))
ax.xaxis.set_major_locator( dates.DayLocator( bymonthday=[1, 8, 15, 22]) )
ax.xaxis.set_major_formatter( dates.DateFormatter("\n%b\n%Y") )
elif dt <= 14.: # less than two weeks
ax.xaxis.set_minor_locator( dates.DayLocator())
ax.xaxis.set_minor_formatter( dates.DateFormatter("%d"))
ax.xaxis.set_major_locator( dates.DayLocator( bymonthday=[1, 15]) )
ax.xaxis.set_major_formatter( dates.DateFormatter("\n%b\n%Y") )
elif dt <= 28.: # less than four weeks
ax.xaxis.set_minor_locator( dates.DayLocator())
ax.xaxis.set_minor_formatter( dates.DateFormatter("%d"))
ax.xaxis.set_major_locator( dates.MonthLocator() )
ax.xaxis.set_major_formatter( dates.DateFormatter("\n%b\n%Y") )
elif dt <= 4 * 30.: # less than four months
ax.xaxis.set_minor_locator( dates.DayLocator( bymonthday=[1, 7, 14, 21] ))
ax.xaxis.set_minor_formatter( dates.DateFormatter("%d"))
ax.xaxis.set_major_locator( dates.MonthLocator())
ax.xaxis.set_major_formatter( dates.DateFormatter("\n%b\n%Y") )
else:
ax.xaxis.set_minor_locator( dates.MonthLocator(interval=2) )
ax.xaxis.set_minor_formatter( dates.DateFormatter("%b"))
ax.xaxis.set_major_locator( dates.MonthLocator(bymonth=[1]) )
ax.xaxis.set_major_formatter( dates.DateFormatter("\n%Y"))
return ax
rc_tsplot = {
'xtick.major.size': 8.,
'xtick.minor.size': 4.,
'xtick.direction': 'out',
'ytick.major.size': 10.,
}
[docs]@skipif(_no_sns)
def tsplot(data, time_col=None, ax=None, parameter=None, rs='1h',
locations=None, plot_kws={}, fmt_axis=True, **kwargs):
"""Plot a timeseries.
:param data: dataframe with data
:param time_col: column name with time. Defaults to the current index.
:param ax: Plot on ax if you would like.
:param parameter: string with parameter to plot. Can only plot 1 at a time.
:type data: pd.DataFrame
:type time_col: string
:type ax: matplotlib axis
:type param: string
"""
assert isinstance(data, pd.DataFrame), "`data` must be a pandas dataframe"
assert parameter in [None, 'pm25', 'pm10', 'o3', 'no2', 'bc', 'co', 'so2'], "Invalid parameter"
if "figsize" not in plot_kws.keys():
plot_kws['figsize'] = (14, 7)
if type(locations) is not list:
locations = [locations]
if ax is None:
ax = plt.gca()
# Deal with ts index issues
if data.index.name is not time_col:
if time_col is not None:
data.index = data[time_col]
else:
if not isinstance(data.index, pd.DatetimeIndex):
data.index = data['date.local']
data.index.name = 'index'
# If parameter is not defined, use the parameter of the first row
if parameter is None:
parameter = data.parameter[0]
data = data[data['parameter'] == parameter]
# Iterate over locations!
for name, group in data.groupby('location'):
if name in locations or locations[0] is None:
_y = group.resample(rs).mean()
ax.plot(_y.value, label=name)
ax.set_ylabel(parameter)
ax.legend( loc = 'best' )
# Set the axes limits
ax.set_ylim([0, ax.get_ylim()[-1]])
if fmt_axis:
ax = tsindex(ax)
return ax