Source code for supy.util._plot

# IQR filling plot:
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from scipy import stats


[docs]def plot_day_clm(df_var, fig=None, ax=None): """Produce a ensemble diurnal climatologies with uncertainties shown in inter-quartile ranges. Parameters ---------- df_var : pd.DataFrame DataFrame containing variables to plot with datetime as index Returns ------- MPL.figure figure showing median lines and IQR in shadings """ if fig is None and ax is None: fig, ax = plt.subplots() elif fig is None: fig = ax.get_figure() elif ax is None: ax = fig.gca() # group by hour and minute grp_sdf_var = df_var.groupby( [df_var.index.hour.rename('hr'), df_var.index.minute.rename('min')]) # get index year = df_var.index.year.min() month = df_var.index.month.min() day = df_var.index.day.min() idx = [pd.datetime(year, month, day, h, m) for h, m in sorted(grp_sdf_var.groups.keys())] idx = pd.date_range(idx[0], idx[-1], periods=len(idx)) idx = mdates.date2num(idx) # calculate quartiles quar_sel_pos_clm = grp_sdf_var.apply( lambda grp: grp.quantile([.75, .5, .25])) # rearrangement quar_sel_pos_clm = quar_sel_pos_clm.unstack() # indexing with proper datetime quar_sel_pos_clm = quar_sel_pos_clm.set_index(idx) # quar_sel_pos_clm = grp_sdf_var.quantile( # [.75, .5, .25]).unstack().set_index(idx) # fig, ax = plt.subplots(1) for var in quar_sel_pos_clm.columns.levels[0]: df_x = quar_sel_pos_clm.loc[:, var] y0 = df_x[0.5] y1, y2 = df_x[0.75], df_x[0.25] y0.plot(ax=ax, label=var).fill_between( quar_sel_pos_clm.index, y1, y2, alpha=0.3) # add legend ax.legend(title='variable') # adjust xticks formar ax.xaxis.set_major_locator(mdates.HourLocator(byhour=np.arange(0, 23, 3))) ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) return fig, ax
# comparison plot with 1:1 line added:
[docs]def plot_comp(df_var, fig=None, ax=None): """Produce a scatter plot with linear regression line to compare simulation results and observations. Parameters ---------- df_var : pd.DataFrame DataFrame containing variables to plot with datetime as index. Two columns, 'Obs' and 'Sim' for observations and simulation results, respectively, must exist. Returns ------- MPL.figure figure showing 1:1 line plot """ if fig is None and ax is None: fig, ax = plt.subplots() elif fig is None: fig = ax.get_figure() elif ax is None: ax = fig.gca() # add regression expression df_var_fit = df_var.dropna(how='any') val_x = df_var_fit['Obs'] val_y = df_var_fit['Sim'] slope, intercept, r_value, p_value, std_err = stats.linregress( val_x, val_y) mae = (val_y - val_x).abs().mean() sns.regplot( x='Obs', y='Sim', data=df_var, ax=ax, fit_reg=True, line_kws={ 'label': "y={0:.2f}x{1}{2:.2f}".format(slope, '+' if intercept > 0 else '', intercept) + '\n' + '$R^2$={0:.4f}'.format(r_value) + '\n' + 'MAE={0:.2f}'.format(mae) + '\n' + 'n={}'.format(df_var.shape[0]) }, ) ax.legend() # set equal plotting range x0, x1 = ax.get_xlim() y0, y1 = ax.get_ylim() lim_low, lim_high = np.min([x0, y0]), np.max([x1, y1]) ax.set_xlim(lim_low, lim_high) ax.set_ylim(lim_low, lim_high) # set 1:1 aspect ratio ax.set_aspect('equal') # add 1:1 line ax.plot([lim_low, lim_high], [lim_low, lim_high], color='red', linewidth=1, zorder=0) # fig = ax.figure return fig, ax