jmquintana79
8/4/2017 - 7:59 AM

## plot quantile forecast

Customized plots for probabilistic forecast. In particular, this functions were used for wind forecast.

``````def plot_quantile_forecast(DF,shead,is_save=False,path_output=None):

"""
DF: columns --> [ dt, real, q5, q10, ..., q95 ]
"""

import numpy as np
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt

# create objects
fig, ax = plt.subplots(figsize=(12,6))

# calculate if any number is the multiple of another number
def multiple(value, multiple):
rest = value % multiple
if rest == 0:
return True
else:
return False

# collect data
mask = np.array([multiple(i.hour, 6) for i in DF.dt.tolist()])
lsx = [ idt.strftime("%Y-%m-%d %Hh") if imask else '' for imask,idt in zip(mask,DF.dt.tolist())]
ix = list(range(0,len(lsx),1))
yreal = DF.real.tolist()
YPRED = DF[[ic for ic in DF.columns.values if 'q' in ic]]

# get list of range
lranges = ["q5-q95","q10-q90","q15-q85","q20-q80","q25-q75","q30-q70","q35-q65","q40-q60","q45-q55"]

# set color list (blues)
lblues = np.linspace(0.1,1.0,len(lranges))

# loop of ranges
for ir,ib in list(zip(lranges,lblues))[:]:
# get name of range limits
ipi,ipf = ir.split("-")
# get required percentiles in each range
ypqi = np.array([float(iv) for iv in YPRED[ipi].values])
ypqf = np.array([float(iv) for iv in YPRED[ipf].values])
# plot range of precentiles
#ax.plot(x_final,ypi,color="grey",linestyle="dashed")
#ax.plot(x_final,ypf,color="grey",linestyle="dashed")
# fill ranges
ax.fill_between(ix,ypqi,ypqf,color=(ib,ib,1.))

# collect extreme percentiles forecast
ypq5 = np.array([float(iv) for iv in YPRED['q5'].values])
ypq95 = np.array([float(iv) for iv in YPRED['q95'].values])
# plot extreme percentiles forecast
ax.plot(ix,ypq5,color="blue")
ax.plot(ix,ypq95,color="blue",label="Prob. Frcst")

# plot real
ax.plot(ix,yreal,color="black",linestyle="dashed" ,label="real")
plt.scatter(ix,yreal,s=20,facecolor="none",edgecolors="black")

# collect p50 forecast
ypq50 = np.array([float(iv) for iv in YPRED['q50'].values])
# plot p50 forecast
ax.plot(ix,ypq50,color="red",label="q50 Frcst")

# x limits
ax.set_xlim([ix[0]-1,ix[-1]+1])
# y limits
ax.set_ylim([0,1])

# xtick
plt.xticks(ix,fontsize='small',rotation='vertical')
ax.set_xticklabels(lsx)
# hide xticks
#plt.tick_params(axis='x',which='both',bottom='off',top='off',labelbottom='off')

# axes labels
plt.ylabel("wp normalized")

# lengend
ax.legend(loc='upper right',fancybox=True, shadow=True, ncol=1,fontsize=10)

# title

# adjust space of chart

# display
if is_save is False: plt.show()
# save
else:
if path_output is None: print('WARNING: it was not specified the output path')
else: plt.savefig(path_output,bbox_inches='tight',transparent=False)

# close plot
plt.close(fig)

# return
return None

## PLOT QUANTILE FORECAST USING BOXPLOTS
import numpy as np
import matplotlib.pyplot as plt
from repository_scores import calculate_pinball_score,rmse,match_index
from repository_functions import multiple
fig, ax = plt.subplots(figsize=(30,10))

## data
lcolq = [ic for ic in DF.columns.values if 'q' in ic]
data = DF[lcolq].as_matrix()
data = np.transpose(data)
ldt = DF.datetime.tolist()
x = list(range(len(ldt)))
y = DF.real.tolist()
predictions = DF['q50'].values
# dates
lmut = np.array([multiple(idt.hour, 6) for idt in ldt])
lsdates = [idt.strftime("%Y-%m-%d %H") if imut else '' for imut,idt in zip(lmut,ldt)]
# match
lmatch = list(DF[['real','q5','q95']].apply(lambda x: True if x[0]>=float('%.1f'%x[1]) and x[0]<=float('%.1f'%x[2]) else False, axis=1))
# scores
pinball_score = np.mean(calculate_pinball_score(DF)['pinball'])
rmse_score = rmse(predictions, y)
vmatch_index = match_index(DF)

# Plot box plot per each line point
boxplot_dict = ax.boxplot(data, positions=x, notch=False)

# Plot a line between the means of each dataset
plt.plot(x, y,linewidth=5,color="black",linestyle="dashed" ,label='real')

# format general labels in x axis
plt.xticks(x,fontsize=20,rotation='vertical')
ax.set_xticklabels(lsdates)
plt.yticks(fontsize=20,rotation='horizontal')

# set limits
#ax.set_ylim([0,1])

# set legend

# set color of box plots
i=0
for b in boxplot_dict['boxes']:
if lmatch[i]: b.set_color('green')
else:b.set_color('red')
i += 1

# title