import IPython.core.display as di
# This line will hide code by default when the notebook is exported as HTML
di.display_html('<script>jQuery(function() {if (jQuery("body.notebook_app").length == 0) { jQuery(".input_area").toggle(); jQuery(".prompt").toggle();}});</script>', raw=True)
# This line will add a button to toggle visibility of code blocks, for use with the HTML export version
di.display_html('''<button onclick="jQuery('.input_area').toggle(); jQuery('.prompt').toggle();">Show/Hide code</button>''', raw=True)
#Allow the created content to be interactivelly ploted inline
%matplotlib inline
#Establish width and height for all plots in the report
#pylab.rcParams['figure.figsize'] = (18, 6) #width, height
#Import needed libraries
import os
from os.path import join, getsize
import pandas as pd
from cycler import cycler
import matplotlib.pyplot as plt
from IPython.display import display
import numpy as np
import collections
import matplotlib as mpl
inline_rc = dict(mpl.rcParams)
#the next cell enables plotting tables without borders
%%html
<style>
table,td,tr,th {border:none!important}
</style>
#Specify the output folder and file containing the CO2MPAS summary output file.
folder = r'C:\Apps\co2mpas_AIO-v1.5.4\CO2MPAS\IPYTHON\Reports_STAMP'
file = '20170210_191149-summary_MT_stamp.xlsx'
infile = join(folder, file)
df=pd.read_excel(infile, 'summary', header=[0, 1, 2, 3], index_col=[0], skiprows=[4])
#Gather and name the basic variables used in the report according to their name in the CO2MPAS output file
NEDCh = df['nedc_h']['prediction']['output']['value']
NEDCth = df['nedc_h']['prediction']['target']['value']
UDCh = df['nedc_h']['prediction']['output']['UDC']
UDCth = df['nedc_h']['prediction']['target']['UDC']
EUDCh = df['nedc_h']['prediction']['output']['EUDC']
EUDCth = df['nedc_h']['prediction']['target']['EUDC']
NEDCl = df['nedc_l']['prediction']['output']['value']
NEDCtl = df['nedc_l']['prediction']['target']['value']
UDCl = df['nedc_l']['prediction']['output']['UDC']
UDCtl = df['nedc_l']['prediction']['target']['UDC']
EUDCl = df['nedc_l']['prediction']['output']['EUDC']
EUDCtl = df['nedc_l']['prediction']['target']['EUDC']
#Obtain the case number and vehicle model from the input file
df['vehicle'] = df.index
cases = df['vehicle'].str.split('_').str[-1].astype('int')
model = df['vehicle'].str.split('_').str[0]
#model = df['vehicle'].str.split('_test').str[0]
#Create a dataframe with this data
valuesDF = pd.DataFrame({'NEDCh': NEDCh,'NEDCth':NEDCth, 'dNEDCh': NEDCh-NEDCth,'UDCh': UDCh,'UDCth':UDCth, 'dUDCh':UDCh-UDCth,'EUDCh': EUDCh,'EUDCth':EUDCth, 'dEUDCh':EUDCh-EUDCth,'NEDCl': NEDCl,'NEDCtl':NEDCtl, 'dNEDCl':NEDCl-NEDCtl,'UDCl': UDCl,'UDCtl':UDCtl, 'dUDCl':UDCl-UDCtl,'EUDCl': EUDCl,'EUDCtl':EUDCtl, 'dEUDCl':EUDCl-EUDCtl,'Case':cases,'Model':model})
#valuesDF = pd.DataFrame({'NEDC': NEDC,'NEDCt':NEDCt, 'dNEDC':NEDC-NEDCt,'UDC': UDC,'UDCt':UDCt, 'dUDC':UDC-UDCt,'EUDC': EUDC,'EUDCt':EUDCt, 'dEUDC':EUDC-EUDCt,'Model':model})
#calculate percentages
valuesDF['NEDC-H error [%]'] = pd.Series((valuesDF.dNEDCh/valuesDF.NEDCth*100), index=valuesDF.index)
valuesDF['UDC-H error [%]'] = pd.Series((valuesDF.dUDCh/valuesDF.UDCth*100), index=valuesDF.index)
valuesDF['EUDC-H error [%]'] = pd.Series((valuesDF.dEUDCh/valuesDF.EUDCth*100), index=valuesDF.index)
valuesDF['NEDC-L error [%]'] = pd.Series((valuesDF.dNEDCl/valuesDF.NEDCtl*100), index=valuesDF.index)
valuesDF['UDC-L error [%]'] = pd.Series((valuesDF.dUDCl/valuesDF.UDCtl*100), index=valuesDF.index)
valuesDF['EUDC-L error [%]'] = pd.Series((valuesDF.dEUDCl/valuesDF.EUDCtl*100), index=valuesDF.index)
valuesDF = valuesDF.dropna()
Error statistics for NEDC, UDC, and EUDC CO$_2$ emission
#Create a dataframe with the NECD, UDC, EUDC error statistics
errorsDF = pd.DataFrame(index=['Averages','StdError','Median','Mode','StdDev','Variance','Kurtosis','Skweness','Range','Minimum','Maximum','Sum','Count','Confidence level (95%)'], columns=['NEDC-H [gCO$_2$ km$^{-1}$]','UDC-H [gCO$_2$ km$^{-1}$]', 'EUDC-H [gCO$_2$ km$^{-1}$]','NEDC-L [gCO$_2$ km$^{-1}$]','UDC-L [gCO$_2$ km$^{-1}$]', 'EUDC-L [gCO$_2$ km$^{-1}$]'])
errorsDF.loc['Averages'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.mean(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.mean(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.mean(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.mean(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.mean(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.mean(),2)})
errorsDF.loc['StdError'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.sem(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.sem(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.sem(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.sem(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.sem(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.sem(),2)})
errorsDF.loc['Median'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.median(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.median(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.median(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.median(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.median(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.median(),2)})
errorsDF.loc['Mode'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.mode().iloc[0],2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.mode().iloc[0],2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.mode().iloc[0],2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.mode().iloc[0],2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.mode().iloc[0],2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.mode().iloc[0],2)})
errorsDF.loc['StdDev'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.std(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.std(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.std(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.std(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.std(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.std(),2)})
errorsDF.loc['Variance'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.var(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.var(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.var(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.var(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.var(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.var(),2)})
errorsDF.loc['Kurtosis'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.kurtosis(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.kurtosis(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.kurtosis(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.kurtosis(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.kurtosis(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.kurtosis(),2)})
errorsDF.loc['Skweness'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.skew(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.skew(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.skew(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.skew(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.skew(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.skew(),2)})
errorsDF.loc['Range'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round((valuesDF.dNEDCh.max()-valuesDF.dNEDCh.min()),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round((valuesDF.dUDCh.max()-valuesDF.dUDCh.min()),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round((valuesDF.dEUDCh.max()-valuesDF.dEUDCh.min()),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round((valuesDF.dNEDCl.max()-valuesDF.dNEDCl.min()),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round((valuesDF.dUDCl.max()-valuesDF.dUDCl.min()),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round((valuesDF.dEUDCl.max()-valuesDF.dEUDCl.min()),2)})
errorsDF.loc['Minimum'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.min(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.min(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.min(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.min(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.min(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.min(),2)})
errorsDF.loc['Maximum'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.max(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.max(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.max(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.max(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.max(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.max(),2)})
errorsDF.loc['Sum'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.sum(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.sum(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.sum(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.sum(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.sum(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.sum(),2)})
errorsDF.loc['Count'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCh.count(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCh.count(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCh.count(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDCl.count(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDCl.count(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDCl.count(),2)})
errorsDF.loc['Confidence level (95%)'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dNEDCh.sem(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dUDCh.sem(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dEUDCh.sem(),2),
'NEDC-L [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dNEDCl.sem(),2), 'UDC-L [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dUDCl.sem(),2), 'EUDC-L [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dEUDCl.sem(),2)})
errorsDF
Error statistics for NEDC, UDC, and EUDC CO$_2$ emission [%]
#Create a dataframe with the NECD, UDC, EUDC error statistics
errorsDF = pd.DataFrame(index=['Averages','StdDev','Minimum','Maximum','Cases in ±4%','Cases in ±2.5%', 'P75-P25'], columns=['NEDC-H [%]','UDC-H [%]', 'EUDC-H [%]','NEDC-L [%]','UDC-L [%]', 'EUDC-L [%]'])
errorsDF.loc['Averages'] = pd.Series({'NEDC-H [%]':round(valuesDF['NEDC-H error [%]'].mean(),2), 'UDC-H [%]':round(valuesDF['UDC-H error [%]'].mean(),2), 'EUDC-H [%]':round(valuesDF['EUDC-H error [%]'].mean(),2),
'NEDC-L [%]':round(valuesDF['NEDC-L error [%]'].mean(),2), 'UDC-L [%]':round(valuesDF['UDC-L error [%]'].mean(),2), 'EUDC-L [%]':round(valuesDF['EUDC-L error [%]'].mean(),2)})
errorsDF.loc['StdDev'] = pd.Series({'NEDC-H [%]':round(valuesDF['NEDC-H error [%]'].std(),2), 'UDC-H [%]':round(valuesDF['UDC-H error [%]'].std(),2), 'EUDC-H [%]':round(valuesDF['EUDC-H error [%]'].std(),2),
'NEDC-L [%]':round(valuesDF['NEDC-L error [%]'].std(),2), 'UDC-L [%]':round(valuesDF['UDC-L error [%]'].std(),2), 'EUDC-L [%]':round(valuesDF['EUDC-L error [%]'].std(),2)})
errorsDF.loc['Minimum'] = pd.Series({'NEDC-H [%]':round(valuesDF['NEDC-H error [%]'].min(),2), 'UDC-H [%]':round(valuesDF['UDC-H error [%]'].min(),2), 'EUDC-H [%]':round(valuesDF['EUDC-H error [%]'].min(),2),
'NEDC-L [%]':round(valuesDF['NEDC-L error [%]'].min(),2), 'UDC-L [%]':round(valuesDF['UDC-L error [%]'].min(),2), 'EUDC-L [%]':round(valuesDF['EUDC-L error [%]'].min(),2)})
errorsDF.loc['Maximum'] = pd.Series({'NEDC-H [%]':round(valuesDF['NEDC-H error [%]'].max(),2), 'UDC-H [%]':round(valuesDF['UDC-H error [%]'].max(),2), 'EUDC-H [%]':round(valuesDF['EUDC-H error [%]'].max(),2),
'NEDC-L [%]':round(valuesDF['NEDC-L error [%]'].max(),2), 'UDC-L [%]':round(valuesDF['UDC-L error [%]'].max(),2), 'EUDC-L [%]':round(valuesDF['EUDC-L error [%]'].max(),2)})
errorsDF.loc['Cases in ±4%'] = pd.Series({'NEDC-H [%]':round(sum(abs(valuesDF['NEDC-H error [%]'])<4)/len(valuesDF['NEDC-H error [%]'])*100,1), 'UDC-H [%]':round(sum(abs(valuesDF['UDC-H error [%]'])<4)/len(valuesDF['UDC-H error [%]'])*100,1), 'EUDC-H [%]':round(sum(abs(valuesDF['EUDC-H error [%]'])<4)/len(valuesDF['EUDC-H error [%]'])*100,1),
'NEDC-L [%]':round(sum(abs(valuesDF['NEDC-L error [%]'])<4)/len(valuesDF['NEDC-L error [%]'])*100,1), 'UDC-L [%]':round(sum(abs(valuesDF['UDC-L error [%]'])<4)/len(valuesDF['UDC-L error [%]'])*100,1), 'EUDC-L [%]':round(sum(abs(valuesDF['EUDC-L error [%]'])<4)/len(valuesDF['EUDC-L error [%]'])*100,1)})
errorsDF.loc['Cases in ±2.5%'] = pd.Series({'NEDC-H [%]':round(sum(abs(valuesDF['NEDC-H error [%]'])<2.5)/len(valuesDF['NEDC-H error [%]'])*100,1), 'UDC-H [%]':round(sum(abs(valuesDF['UDC-H error [%]'])<2.5)/len(valuesDF['UDC-H error [%]'])*100,1), 'EUDC-H [%]':round(sum(abs(valuesDF['EUDC-H error [%]'])<2.5)/len(valuesDF['EUDC-H error [%]'])*100,1),
'NEDC-L [%]':round(sum(abs(valuesDF['NEDC-L error [%]'])<2.5)/len(valuesDF['NEDC-L error [%]'])*100,1), 'UDC-L [%]':round(sum(abs(valuesDF['UDC-L error [%]'])<2.5)/len(valuesDF['UDC-L error [%]'])*100,1), 'EUDC-L [%]':round(sum(abs(valuesDF['EUDC-L error [%]'])<2.5)/len(valuesDF['EUDC-L error [%]'])*100,1)})
errorsDF.loc['P75-P25'] = pd.Series({'NEDC-H [%]':round(np.percentile(valuesDF['NEDC-H error [%]'],75)-np.percentile(valuesDF['NEDC-H error [%]'],25),2), 'UDC-H [%]':round(np.percentile(valuesDF['UDC-H error [%]'],75)-np.percentile(valuesDF['UDC-H error [%]'],25),2), 'EUDC-H [%]':round(np.percentile(valuesDF['EUDC-H error [%]'],75)-np.percentile(valuesDF['EUDC-H error [%]'],25),2),
'NEDC-L [%]':round(np.percentile(valuesDF['NEDC-L error [%]'],75)-np.percentile(valuesDF['NEDC-L error [%]'],25),2), 'UDC-L [%]':round(np.percentile(valuesDF['UDC-L error [%]'],75)-np.percentile(valuesDF['UDC-L error [%]'],25),2), 'EUDC-L [%]':round(np.percentile(valuesDF['EUDC-L error [%]'],75)-np.percentile(valuesDF['EUDC-L error [%]'],25),2)})
errorsDF
Distribution of the NEDC, UDC and EUDC errors [%]
mydict = ([('NEDC', 0), ('UDC', 1), ('EUDC', 2)])
mydict = collections.OrderedDict(mydict)
for cycle in mydict:
if cycle == 'NEDC':
boxcolor = 'green'
elif cycle == 'UDC':
boxcolor = 'blue'
else:
boxcolor = 'red'
# Create a figure instance
fig = plt.figure(1, figsize=(14, 7))
# Create an axes instance
ax = fig.add_subplot(111)
hist = valuesDF[cycle+'-H error [%]'].hist(bins=np.arange(min(valuesDF['UDC-H error [%]']), max(valuesDF['UDC-H error [%]']) + 0.5, 0.5), color=boxcolor, label = 'High')
hist = valuesDF[cycle+'-L error [%]'].hist(bins=np.arange(min(valuesDF['UDC-L error [%]']), max(valuesDF['UDC-L error [%]']) + 0.5, 0.5), color=boxcolor, alpha = 0.5, label = 'Low')
hist.set_xlabel(cycle+" error [%]",fontsize=14)
hist.legend(prop={'size': 15})
hist.set_ylabel("frequency",fontsize=14)
hist.set_ylim(0,450)
plt.title(cycle+' CO$_2$ emission error distribution', fontsize=20)
plt.ylabel("frequency",fontsize=18)
plt.tick_params(axis='x', which='major', labelsize=16)
plt.tick_params(axis='y', which='major', labelsize=16)
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
ax.set_xlim(-20, 20)
plt.show()
Comparative emission error per driving cycle (gCO$_2$ km$^{-1}$)
#Alternatively show boxplots
toboxplot = [valuesDF['NEDC-H error [%]'],valuesDF['NEDC-L error [%]'],valuesDF['UDC-H error [%]'],valuesDF['UDC-L error [%]'],
valuesDF['EUDC-H error [%]'],valuesDF['EUDC-L error [%]']]
# Create a figure instance
fig = plt.figure(1, figsize=(14, 7))
# Create an axes instance
ax = fig.add_subplot(111)
# Create the boxplot with fill color
bp = ax.boxplot(toboxplot, sym='', patch_artist=True, whis=10000, showmeans=True, meanprops=(dict(marker='o',markerfacecolor='yellow')))
for box in bp['boxes']:
# change outline color
box.set( color='black', linewidth=1)
# change fill color
box.set( facecolor = '#b78adf' )
## Custom x-axis labels
ax.set_xticklabels(['NEDC-H','NEDC-L', 'UDC-H','UDC-L','EUDC-H','EUDC-L'],fontsize=20)
## Remove top axes and right axes ticks
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
#Set y axis title
plt.title('CO$_2$ emission error by driving cycle', fontsize=20)
plt.ylabel("error [%]",fontsize=18)
plt.tick_params(axis='y', which='major', labelsize=16)
ax.set_ylim(-25, 25)
plt.setp(bp['medians'], color = 'purple', linewidth = 2)
plt.show()
print('The purple box represents the 1st and 3rd quartile.\nThe dark purple line is the median.\nThe yellow dot is the mean.\nthe whiskers show the min and max values.')
#Print a dictionary with the tested technologies and their identification codes
tec = pd.DataFrame(index=['Base case','Gear configuration A','Gear configuration B','No Start/Stop','No Break energy recuperation','Variable valve lifting','Direct injection/Multipoint injection','Thermal management'])
tec['Technology code'] = ['BC','GCA','GCB','NOSS','NOBERS','VVL','DI/MPI','ThM']
tec.columns.name='Technology type'
tec
#Function that assigns the number of case to the specific technology tested for each vehicle model
def assign_technol_perCarAndCase(df):
#looks for the case # in the input file and assigns a technology
df_basecase = df[valuesDF['Case'] <= 27]
df_gca = df[(valuesDF['Case'] > 27) & (valuesDF['Case'] <= 54)]
df_gcb = df[(valuesDF['Case'] > 54) & (valuesDF['Case'] <= 81)]
df_noss = df[(valuesDF['Case'] > 81) & (valuesDF['Case'] <= 108)]
df_nobers = df[(valuesDF['Case'] > 108) & (valuesDF['Case'] <= 135)]
#some vehicles have more possible technologies than others (long vs short) and an additional technology assignment is performed for the former group
In_long = (valuesDF['Model'] == 'Vehicle04') | (valuesDF['Model'] == 'Vehicle02') | (valuesDF['Model'] == 'Vehicle10') | (valuesDF['Model'] == 'Vehicle06') | (valuesDF['Model'] == 'Vehicle11') | (valuesDF['Model'] == 'Vehicle09')| (valuesDF['Model'] == 'Vehicle05')
In_short = (valuesDF['Model'] == 'Vehicle12') | (valuesDF['Model'] == 'Vehicle01') | (valuesDF['Model'] == 'Vehicle03') | (valuesDF['Model'] == 'Vehicle07') | (valuesDF['Model'] == 'Vehicle08')
I_vvl = (valuesDF['Case'] >= 136) & (valuesDF['Case'] <= 162)
df_vvl = df[In_long & I_vvl]
I_dimpi = (valuesDF['Case'] >= 163) & (valuesDF['Case'] <= 189)
df_dimpi = df[In_long & I_dimpi]
I_short_tm = (valuesDF['Case'] >= 136)
I_long_tm = (valuesDF['Case'] >= 190)
I_tm = (In_short & I_short_tm) | (In_long & I_long_tm)
df_tm = df[I_tm]
#Append to the original DF a column with the technology IDcode
pd.options.mode.chained_assignment = None # default='warn'
try:
df_basecase.loc[:,'Tecno'] = 'BC'
except:
pass
try:
df_gca.loc[:,'Tecno'] = 'GCA'
except:
pass
try:
df_gcb.loc[:,'Tecno'] = 'GCB'
except:
pass
try:
df_noss.loc[:,'Tecno'] = 'NOSS'
except:
pass
try:
df_nobers.loc[:,'Tecno'] = 'NOBERS'
except:
pass
try:
df_vvl.loc[:,'Tecno'] = 'VVL'
except:
pass
try:
df_dimpi.loc[:,'Tecno'] = 'DI/MPI'
except:
pass
try:
df_tm.loc[:,'Tecno'] = 'ThM'
except:
pass
bigdata = pd.concat([df_basecase,df_gca,df_gcb,df_noss,df_nobers,df_vvl,df_dimpi,df_tm], ignore_index=False)
return bigdata
#Plot the NEDC errors per technology type in a boxplot
tech = assign_technol_perCarAndCase(valuesDF)
techBC = tech[tech['Tecno'] == 'BC']
techGCA = tech[tech['Tecno'] == 'GCA']
techGCB = tech[tech['Tecno'] == 'GCB']
techNOSS = tech[tech['Tecno'] == 'NOSS']
techBERS = tech[tech['Tecno'] == 'NOBERS']
techVVL = tech[tech['Tecno'] == 'VVL']
techDIMPI = tech[tech['Tecno'] == 'DI/MPI']
#techNOLB = tech[tech['Tecno'] == 'NOLB']
techThM = tech[tech['Tecno'] == 'ThM']
mydict = ([('NEDC', 0), ('UDC', 1), ('EUDC', 2)])
mydict = collections.OrderedDict(mydict)
for cycle in mydict:
techboxplot = [techBC[cycle+'-H error [%]'],techGCA[cycle+'-H error [%]'],techGCB[cycle+'-H error [%]'],techNOSS[cycle+'-H error [%]'],techBERS[cycle+'-H error [%]'],techVVL[cycle+'-H error [%]'],techDIMPI[cycle+'-H error [%]'],techThM[cycle+'-H error [%]']]
if cycle == 'NEDC':
boxcolor = 'green'
elif cycle == 'UDC':
boxcolor = 'blue'
else:
boxcolor = 'red'
# Create a figure instance
fig = plt.figure(1, figsize=(14, 7))
# Create an axes instance
ax = fig.add_subplot(111)
# Create the boxplot with fill color
bp = ax.boxplot(techboxplot, sym='', patch_artist=True, whis=10000, showmeans=True, meanprops=(dict(marker='o',markerfacecolor='yellow')))
for box in bp['boxes']:
# change outline color
box.set( color='black', linewidth=1)
# change fill color
box.set(facecolor = boxcolor)
## Custom x-axis labels
ax.set_xticklabels(['BC', 'GCA', 'GCB','NOSS','NOBERS','VVL','DI/MPI','ThM'],fontsize=20)
## Remove top axes and right axes ticks
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
#Set y axis title
plt.title(cycle+'-H CO$_2$ emission error by technology type', fontsize=20)
plt.ylabel("error [%]",fontsize=18)
plt.tick_params(axis='y', which='major', labelsize=18)
# ax.set_ylim(-20, 20)
plt.setp(bp['medians'], color = 'purple', linewidth = 2)
plt.show()
print('The green box represents the 1st and 3rd quartile.\nThe dark purple line is the median.\nThe yellow dot is the mean.\nthe whiskers show the min and max values.')
print('\nDescriptive statistics for '+cycle+'-H CO2 emission error per technology type')
grouped = tech.groupby('Tecno')
gmean = grouped[cycle+'-H error [%]'].mean()
gsem = grouped[cycle+'-H error [%]'].sem()
gmedian = grouped[cycle+'-H error [%]'].median()
gstd = grouped[cycle+'-H error [%]'].std()
gvar = grouped[cycle+'-H error [%]'].var()
gskew = grouped[cycle+'-H error [%]'].skew()
grange = grouped[cycle+'-H error [%]'].max()-grouped.dNEDCh.min()
gmin = grouped[cycle+'-H error [%]'].min()
gmax = grouped[cycle+'-H error [%]'].max()
gsum = grouped[cycle+'-H error [%]'].sum()
gcount = grouped[cycle+'-H error [%]'].count()
gCI95 = 2*grouped[cycle+'-H error [%]'].sem()
errorsTec = pd.DataFrame(index=['Averages','StdError','Median','StdDev','Variance','Kurtosis','Skweness','Range','Minimum','Maximum','Sum','Count','Confidence level (95%)'], columns=['BC','GCA', 'GCB','NOSS','NOBERS','VVL','DI/MPI','ThM'])
errorsTec.loc['Averages'] = pd.Series.round(gmean,2)
errorsTec.loc['StdError'] = pd.Series.round(gsem,2)
errorsTec.loc['Median'] = pd.Series.round(gmedian,2)
errorsTec.loc['StdDev'] = pd.Series.round(gstd,2)
errorsTec.loc['Variance'] = pd.Series.round(gvar,2)
errorsTec.loc['Kurtosis'] = [round(techBC[cycle+'-H error [%]'].kurtosis(),2),round(techGCA[cycle+'-H error [%]'].kurtosis(),2),round(techGCB[cycle+'-H error [%]'].kurtosis(),2),round(techNOSS[cycle+'-H error [%]'].kurtosis(),2),round(techBERS[cycle+'-H error [%]'].kurtosis(),2),round(techVVL[cycle+'-H error [%]'].kurtosis(),2),round(techDIMPI[cycle+'-H error [%]'].kurtosis(),2),round(techThM[cycle+'-H error [%]'].kurtosis(),2)]
errorsTec.loc['Skweness'] = pd.Series.round(gskew,2)
errorsTec.loc['Range'] = pd.Series.round(grange,2)
errorsTec.loc['Minimum'] = pd.Series.round(gmin,2)
errorsTec.loc['Maximum'] = pd.Series.round(gmax,2)
errorsTec.loc['Sum'] = pd.Series.round(gsum)
errorsTec.loc['Count'] = pd.Series.round(gcount)
errorsTec.loc['Confidence level (95%)'] = pd.Series.round(gCI95,2)
errorsTec.columns.name=cycle+'-H error'
display(errorsTec)
Glossary of vehicle models and number of test cases considered in the report
mod_cases_stats = valuesDF.groupby(['Model'],as_index=False).count()
mod_cases_stats['Brand and model'] = ['Vehicle 01','Vehicle 02','Vehicle 03','Vehicle 04','Vehicle 05','Vehicle 06','Vehicle 07','Vehicle 08','Vehicle 09','Vehicle 10','Vehicle 11','Vehicle 12']
cols = mod_cases_stats.columns.tolist()
cols = cols[-1:] + cols[:2]
mod_cases_stats = mod_cases_stats[cols]
mod_cases_stats
NEDC, UDC, and EUDC CO$_2$ emission error per vehicle model
#In order to create statistic tables and plots for each model car, a numeric car ID 'cid' has to be assigned to each vehicle
tech = assign_technol_perCarAndCase(valuesDF)
Carlist = list(sorted(tech['Model'].unique()))
Cidlist = list(range(len(Carlist)))
tech.cid = tech['Model'].replace(Carlist, Cidlist, regex = True)
tech['cod'] = tech.cid
dictecnos = {'BC':'o', 'GCA':'s', 'GCB':'v', 'NOSS':'p','NOBERS':'D','VVL':'4','DI/MPI':'+','NOLB':'h','ThM':'*'}
#Create a table with the error statistics for each car model
for x in Carlist:
Car = tech[tech['Model'] == x]
grouped = Car.groupby('Tecno')
CarDF = pd.DataFrame(index=['Averages','Median', 'StdDev'], columns=['NEDC-H [gCO$_2$ km$^{-1}$]','UDC-H [gCO$_2$ km$^{-1}$]', 'EUDC-H [gCO$_2$ km$^{-1}$]'])
CarDF.loc['Averages'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(Car.dNEDCh.mean(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(Car.dUDCh.mean(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(Car.dEUDCh.mean(),2)})
CarDF.loc['Median'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(Car.dNEDCh.median(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(Car.dUDCh.median(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(Car.dEUDCh.median(),2)})
CarDF.loc['StdDev'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(Car.dNEDCh.std(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(Car.dUDCh.std(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(Car.dEUDCh.std(),2)})
CarDF.columns.name=Car.iat[0,5]
display(CarDF)
CarDFF = pd.DataFrame(index=['Averages','Median', 'StdDev'], columns=['NEDC-H [%]','NEDC-L [%]'])
CarDFF.loc['Averages'] = pd.Series({'NEDC-H [%]':round(Car['NEDC-H error [%]'].mean(),2), 'NEDC-L [%]':round(Car['NEDC-L error [%]'].mean(),2)})
CarDFF.loc['Median'] = pd.Series({'NEDC-H [%]':round(Car['NEDC-H error [%]'].median(),2), 'NEDC-L [%]':round(Car['NEDC-L error [%]'].median(),2)})
CarDFF.loc['StdDev'] = pd.Series({'NEDC-H [%]':round(Car['NEDC-H error [%]'].std(),2), 'NEDC-L [%]':round(Car['NEDC-L error [%]'].std(),2)})
CarDFF.columns.name=Car.iat[0,5]
display(CarDFF)
#plot the CO2 emission error histogram per vehicle model and cycle
mydict = ([('NEDC', 0), ('UDC', 1), ('EUDC', 2)])
mydict = collections.OrderedDict(mydict)
for cycle in mydict:
if cycle == 'NEDC':
boxcolor = 'green'
elif cycle == 'UDC':
boxcolor = 'blue'
else:
boxcolor = 'red'
fig = plt.figure(1, figsize=(14, 7))
plt.title(Car.iat[0,5],fontsize=20)
plot = fig.add_subplot(111)
plot.tick_params(axis='x', which='major', labelsize=14)
plot.tick_params(axis='y', which='major', labelsize=14)
plot.set_xlim(-20, 20)
plot.get_xaxis().tick_bottom()
plot.get_yaxis().tick_left()
car_hist = Car[cycle+'-H error [%]'].hist(bins=25, color=boxcolor)
car_hist.set_xlabel(cycle+" CO$_2$ emission error [%]",fontsize=20)
car_hist.set_ylabel("frequency",fontsize=20)
plt.show()
#plot the emission error per case, model, and cycle
fig = plt.figure(1, figsize=(14, 7))
plt.title(Car.iat[0,5],fontsize=20)
plot = fig.add_subplot(111)
plot.tick_params(axis='x', which='major', labelsize=14)
plot.tick_params(axis='y', which='major', labelsize=14)
plot.set_xlim(0, 240)
plot.set_ylim(-20,20)
plot.get_xaxis().tick_bottom()
plot.get_yaxis().tick_left()
for key, group in grouped:
plt.plot(group['Case'], group[cycle+'-H error [%]'], color=boxcolor, marker=dictecnos[key], label = key, linestyle='')
first_legend = plt.legend(numpoints=1, bbox_to_anchor=(1.0, 1.), loc=1, borderaxespad=0.)
plot.ax = plt.gca().add_artist(first_legend)
plot.set_xlabel("Case #",fontsize=20)
plot.set_ylabel(cycle+" error [%]",fontsize=20)
line1 = plot.axhline(y=-2.5, color='grey', linestyle='-.', label='± 2.5 %')
line2 = plot.axhline(y=2.5, color='grey', linestyle='-.')
line3 = plot.axhline(y=-4, color='black', linestyle='--', label='± 4.0 %')
line4 = plot.axhline(y=4, color='black', linestyle='--')
plt.legend(handles=[line1, line3], loc = 3)
plt.show()