In [1]:
# path = r'C:/Users/dimit/Desktop/20191107_213830-summary_4.1.10.xlsx'
# # path = r'C:/Users/dimit/Desktop/20190729_121722-summary_v3.0.0.xlsx'

# list_header = [0, 1, 2, 3,]
# if '4.1.10' in path: 
#     list_header = [0, 1, 2, 3, 4]

# df = pd.read_excel(path, 'summary', header=list_header, index_col=[0], skiprows=[4])

# files = list(df.index)
# path_input = 'C:/Work/co2mpasdb/inputs/'
# input_names = os.listdir(path_input)
# dict_input_names = dict()
# for f in input_names:
#     nn = f.replace(' ', '_').split('.xlsx')[0].split('.XLSX')[0].replace('(', '').replace(')', '')
#     dict_input_names[nn] = f.split('.xlsx')[0].split('.XLSX')[0]

# import os
# gb_dict = dict()
# mt, at, cvt = 1, 1, 1
# for f in files: 
#     f_name = f
#     if '4.1.10' in path:
#         f_name = dict_input_names[f.replace(' ', '_')]
#     _df = pd.read_excel(path_input + f_name + '.xlsx', 'Inputs')[['Name', 'Value']].dropna()
#     v = _df.loc[_df['Name']=='gear_box_type', 'Value'].values[0]
#     if v == 'manual': 
#         gb_dict[f] = ['MT_' + ('0' + str(mt))[-2:]]
#         mt += 1
#     if v == 'automatic': 
#         gb_dict[f] = ['AT_' + ('0' + str(at))[-2:]]
#         at += 1
#     if v == 'CVT':
#         gb_dict[f] = ['CVT_' + ('0' + str(cvt))[-2:]]
#         cvt += 1

# pd.DataFrame.from_dict(gb_dict, orient='index', columns=['gb']).to_excel(path.split('.xlsx')[0]+'_gb_type.xlsx')
In [2]:
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)
In [3]:
#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
In [5]:
#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 collections
import numpy as np
import matplotlib as mpl
inline_rc = dict(mpl.rcParams)
pd.options.display.max_rows=1000
#the next cell enables plotting tables without borders

# To hide warnings
import warnings
warnings.filterwarnings('ignore')
In [6]:
%%html
<style>
table,td,tr,th {border:none!important}
</style>

Summary report of the CO2MPAS WLTP to NEDC CO2 emission simulation model - Real vehicles (v.3.0.x)

Visit the CO2MPAS home page

In [7]:
#Specify the output folder and file containing the CO2MPAS summary output file.
folder = r'd:/Documents/CO2MPAS/co2mpas_validation_reports/'
file = '20190729_121722-summary_v3.0.0_ANON.xlsx'
infile = join(folder, file)
df=pd.read_excel(infile, 'ANON', header=[0, 1, 2, 3], index_col=[0], skiprows=[4])
In [8]:
#Gather and name the basic variables used in the report according to their name in the CO2MPAS output file
NEDC = df['nedc_h']['prediction']['output']['declared_value']
NEDCl = df['nedc_l']['prediction']['output']['declared_value']
NEDCt = df['nedc_h']['prediction']['target']['declared_value'].fillna(df['nedc_h']['prediction']['target']['value'])
NEDCtl = df['nedc_l']['prediction']['target']['declared_value'].fillna(df['nedc_l']['prediction']['target']['value'])
UDC = df['nedc_h']['prediction']['output']['UDC']
UDCl = df['nedc_l']['prediction']['output']['UDC']
UDCt = df['nedc_h']['prediction']['target']['UDC']
UDCtl = df['nedc_l']['prediction']['target']['UDC']
EUDC = df['nedc_h']['prediction']['output']['EUDC']
EUDCl = df['nedc_l']['prediction']['output']['EUDC']
EUDCt = df['nedc_h']['prediction']['target']['EUDC']
EUDCtl = df['nedc_l']['prediction']['target']['EUDC']
#Obtain the case number and vehicle model from the input file
df['vehicle'] = df.index
model = df['vehicle'].str.split('_test').str[0]
#Create a dataframe with this data
valuesDF = pd.DataFrame({'NEDC': NEDC,'NEDCt':NEDCt,'NEDCtl':NEDCtl, 'dNEDC':NEDC-NEDCt,'dNEDCl':NEDCl-NEDCtl,'UDC': UDC,'UDCt':UDCt, 'UDCtl':UDCtl,'dUDC':UDC-UDCt,'dUDCl':UDCl-UDCtl,'EUDC': EUDC,'EUDCt':EUDCt,'EUDCtl':EUDCtl, 'dEUDC':EUDC-EUDCt,'dEUDCl':EUDCl-EUDCtl,'Model':model})   
#calculate percentages
valuesDF['NEDC-H error [%]'] = pd.Series((valuesDF.dNEDC/valuesDF.NEDCt*100), index=valuesDF.index)
valuesDF['UDC-H error [%]'] = pd.Series((valuesDF.dUDC/valuesDF.UDCt*100), index=valuesDF.index)
valuesDF['EUDC-H error [%]'] = pd.Series((valuesDF.dEUDC/valuesDF.EUDCt*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['NEDC-H error [%]'] = valuesDF['NEDC-H error [%]'].dropna()
valuesDF['UDC-H error [%]'] = valuesDF['UDC-H error [%]'].dropna()
valuesDF['EUDC-H error [%]'] = valuesDF['EUDC-H error [%]'].dropna()
valuesDF['NEDC-L error [%]'] = valuesDF['NEDC-L error [%]'].dropna()
valuesDF['UDC-L error [%]'] = valuesDF['UDC-L error [%]'].dropna()
valuesDF['EUDC-L error [%]'] = valuesDF['EUDC-L error [%]'].dropna()

Section 1. Performance of the model. All vehicles

Error statistics for CO2 emission per driving cycle

Error statistics for NEDC, UDC, and EUDC CO2 emission [gCO 2 km −1 ]

In [9]:
#Create a dataframe with the NECD, UDC, EUDC error statistics
errorsDF = pd.DataFrame(index=['Averages','StdError','Median','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.dNEDC.mean(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.mean(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.sem(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.sem(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.median(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.median(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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['StdDev'] = pd.Series({'NEDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dNEDC.std(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.std(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.var(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.var(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.kurtosis(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.kurtosis(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.skew(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.skew(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.max()-valuesDF.dNEDC.min()),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round((valuesDF.dUDC.max()-valuesDF.dUDC.min()),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round((valuesDF.dEUDC.max()-valuesDF.dEUDC.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.dNEDC.min(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.min(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.max(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.max(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.sum(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.sum(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.count(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dUDC.count(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':round(valuesDF.dEUDC.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.dNEDC.sem(),2), 'UDC-H [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dUDC.sem(),2), 'EUDC-H [gCO$_2$ km$^{-1}$]':2*round(valuesDF.dEUDC.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
Out[9]:
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}$]
Averages -0.53 -3.93 1.05 -0.75 -4.48 0.12
StdError 0.54 1.25 0.57 0.92 1.73 1.13
Median -0.65 -5.41 1.16 -0.59 -3.85 0.07
StdDev 4.03 8.37 3.85 4.34 6.7 4.36
Variance 16.21 70.02 14.82 18.82 44.91 19.01
Kurtosis -0.41 0.06 -0.37 0.75 -1.09 5.43
Skweness 0.19 0.23 -0.11 -0.85 -0.11 -1.86
Range 17.16 37.5 17.13 16.78 20.66 18.66
Minimum -8.46 -24.01 -7.34 -12.15 -14.37 -12.85
Maximum 8.7 13.49 9.79 4.63 6.29 5.81
Sum -29.93 -177.01 47.07 -16.59 -67.15 1.81
Count 56 45 45 22 15 15
Confidence level (95%) 1.08 2.5 1.14 1.84 3.46 2.26

Error statistics for NEDC, UDC, and EUDC CO 2 emission [%]

In [10]:
#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%'], 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 [%]'].dropna())<4)/len(valuesDF['NEDC-H error [%]'].dropna())*100,1), 'UDC-H [%]':round(sum(abs(valuesDF['UDC-H error [%]'].dropna())<4)/len(valuesDF['UDC-H error [%]'].dropna())*100,1), 'EUDC-H [%]':round(sum(abs(valuesDF['EUDC-H error [%]'].dropna())<4)/len(valuesDF['EUDC-H error [%]'].dropna())*100,1),'NEDC-L [%]':round(sum(abs(valuesDF['NEDC-L error [%]'].dropna())<4)/len(valuesDF['NEDC-L error [%]'].dropna())*100,1), 'UDC-L [%]':round(sum(abs(valuesDF['UDC-L error [%]'].dropna())<4)/len(valuesDF['UDC-L error [%]'].dropna())*100,1), 'EUDC-L [%]':round(sum(abs(valuesDF['EUDC-L error [%]'].dropna())<4)/len(valuesDF['EUDC-L error [%]'].dropna())*100,1)})
errorsDF.loc['Cases in ±2.5%'] = pd.Series({'NEDC-H [%]':round(sum(abs(valuesDF['NEDC-H error [%]'].dropna())<2.5)/len(valuesDF['NEDC-H error [%]'].dropna())*100,1), 'UDC-H [%]':round(sum(abs(valuesDF['UDC-H error [%]'].dropna())<2.5)/len(valuesDF['UDC-H error [%]'].dropna())*100,1), 'EUDC-H [%]':round(sum(abs(valuesDF['EUDC-H error [%]'].dropna())<2.5)/len(valuesDF['EUDC-H error [%]'].dropna())*100,1),'NEDC-L [%]':round(sum(abs(valuesDF['NEDC-L error [%]'].dropna())<2.5)/len(valuesDF['NEDC-L error [%]'].dropna())*100,1), 'UDC-L [%]':round(sum(abs(valuesDF['UDC-L error [%]'].dropna())<2.5)/len(valuesDF['UDC-L error [%]'].dropna())*100,1), 'EUDC-L [%]':round(sum(abs(valuesDF['EUDC-L error [%]'].dropna())<2.5)/len(valuesDF['EUDC-L error [%]'].dropna())*100,1)})
errorsDF.loc['P75-P25'] = pd.Series({'NEDC-H [%]':round(valuesDF['NEDC-H error [%]'].quantile(0.75)-valuesDF['NEDC-H error [%]'].quantile(0.25),2), 'UDC-H [%]':round(valuesDF['UDC-H error [%]'].quantile(0.75)-valuesDF['UDC-H error [%]'].quantile(0.25),2), 'EUDC-H [%]':round(valuesDF['EUDC-H error [%]'].quantile(0.75)-valuesDF['EUDC-H error [%]'].quantile(0.25),2),'NEDC-L [%]':round(valuesDF['NEDC-L error [%]'].quantile(0.75)-valuesDF['NEDC-L error [%]'].quantile(0.25),2), 'UDC-L [%]':round(valuesDF['UDC-L error [%]'].quantile(0.75)-valuesDF['UDC-L error [%]'].quantile(0.25),2), 'EUDC-L [%]':round(valuesDF['EUDC-L error [%]'].quantile(0.75)-valuesDF['EUDC-L error [%]'].quantile(0.25),2)})
errorsDF
Out[10]:
NEDC-H [%] UDC-H [%] EUDC-H [%] NEDC-L [%] UDC-L [%] EUDC-L [%]
Averages -0.23 -1.81 1.02 -0.31 -2.7 0.58
StdDev 2.75 4.66 3.06 3.09 4.22 3.24
Minimum -5 -10.61 -4.21 -6.23 -9.25 -6.87
Maximum 7.29 10.75 8.69 4.13 3.95 6.01
Cases in ±4% 87.5 51.1 84.4 81.8 66.7 80
Cases in ±2.5% 57.1 33.3 53.3 54.5 33.3 60
P75-P25 3.7 4.4 4.85 4.34 6.07 2.94

Distribution of the NEDC, UDC and EUDC errors [%]

In [11]:
mydict = ([('NEDC', 0), ('UDC', 1), ('EUDC', 2)])
mydict = collections.OrderedDict(mydict)
for cycle in mydict:
    if cycle == 'NEDC':
        boxcolor = ['forestgreen', 'limegreen']
    elif cycle == 'UDC':
        boxcolor = ['darkblue', 'blue']
    else:
        boxcolor = ['red', 'coral']
    # 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(-15, 15, 1), color=boxcolor[0], alpha=0.5, label = 'High', ec='black')
    hist = valuesDF[cycle+'-L error [%]'].hist(bins=np.arange(-15, 15, 1), color=boxcolor[1], alpha=0.5, label='Low', ec='black')
    hist.set_xlabel(cycle+" error [%]",fontsize=14)
    hist.set_ylabel("frequency",fontsize=14)
    hist.set_ylim(0,12)
    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(-15, 15)
    plt.legend()
    plt.show()

Section 2. Performance of the model. Statistics per vehicle model

NEDC, UDC, and EUDC CO2 emission error [%] per vehicle model

In [12]:
Carlist = list(valuesDF['Model'])
Cidlist = list(range(len(Carlist)))
valuesDF.cid = valuesDF['Model'].replace(Carlist, Cidlist, regex = False)
valuesDF['cod'] = valuesDF.cid
#Create a table with the error statistics for each car model
CarDF = pd.DataFrame(columns=['NEDC-H error [%]','UDC-H error [%]', 'EUDC-H error [%]',
                             'NEDC-L error [%]','UDC-L error [%]', 'EUDC-L error [%]'])
for x in Carlist:
    Car = valuesDF[valuesDF['Model'] == x]
    CarDF.loc[x] = pd.Series({'NEDC-H error [%]':round(Car['NEDC-H error [%]'].mean(),2), 'UDC-H error [%]':round(Car['UDC-H error [%]'].mean(),2), 'EUDC-H error [%]':round(Car['EUDC-H error [%]'].mean(),2),
                            'NEDC-L error [%]':round(Car['NEDC-L error [%]'].mean(),2), 'UDC-L error [%]':round(Car['UDC-L error [%]'].mean(),2), 'EUDC-L error [%]':round(Car['EUDC-L error [%]'].mean(),2)})
CarDF.columns.name='Error'
display(CarDF)
mydict = ([('NEDC-H', 0), ('UDC-H', 1), ('EUDC-H', 2),('NEDC-L', 3), ('UDC-L', 4), ('EUDC-L', 5)])
mydict = collections.OrderedDict(mydict)
for cycle in mydict:
    if cycle == 'NEDC-H':
        boxcolor = 'green'
    elif cycle == 'NEDC-L':
        boxcolor = 'green'
    elif cycle == 'UDC-H':
        boxcolor = 'blue'
    elif cycle == 'UDC-L':
        boxcolor = 'blue'
    else:
        boxcolor = 'red'
    #plot the emission error per model, and cycle
    fig = plt.figure(1, figsize=(14, 7))
    _valuesDF = valuesDF[['Model', 'cod', cycle+' error [%]']].dropna()
    labels = ['{0}'.format(i) for i in _valuesDF['Model']]
    plt.title(cycle+" error [%] per real vehicle",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(-1, 65)
    plot.set_ylim(-12,12)
    plot.get_xaxis().tick_bottom()
    plot.get_yaxis().tick_left()
#     plt.scatter(valuesDF['Case'],valuesDF[cycle+' error [%]'], color=boxcolor, marker = 'o')
    plt.scatter(_valuesDF['cod'],_valuesDF[cycle+' error [%]'], color=boxcolor, marker = 'o')
#     for label, x, y in zip(labels, valuesDF['Case'], valuesDF[cycle+' error [%]']):
    for label, x, y in zip(labels, _valuesDF['cod'], _valuesDF[cycle+' error [%]'].fillna(0)):
        plt.annotate(label, xy = (x, y), size = 12)
    plot.set_xlabel("Vehicle #",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() 
Error NEDC-H error [%] UDC-H error [%] EUDC-H error [%] NEDC-L error [%] UDC-L error [%] EUDC-L error [%]
MT_01 -2.88 NaN NaN 3.25 NaN NaN
AT_01 3.74 NaN NaN NaN NaN NaN
MT_02 2.74 NaN NaN 1.03 NaN NaN
AT_02 -3.94 NaN NaN 2.27 NaN NaN
AT_03 -0.66 NaN NaN -2.30 NaN NaN
AT_04 3.79 NaN NaN NaN NaN NaN
MT_03 7.29 NaN NaN 3.87 NaN NaN
MT_04 -0.06 NaN NaN 0.29 NaN NaN
MT_05 3.26 4.12 2.49 NaN NaN NaN
MT_06 3.65 9.59 -1.15 NaN NaN NaN
MT_07 0.67 -4.10 5.44 NaN NaN NaN
AT_05 -5.00 -6.88 -3.25 NaN NaN NaN
MT_08 -2.72 -7.79 2.12 NaN NaN NaN
AT_06 -4.17 -8.07 -0.23 NaN NaN NaN
AT_07 1.61 -0.78 3.54 NaN NaN NaN
AT_08 0.92 -3.24 4.29 NaN NaN NaN
MT_09 -1.40 1.35 -3.35 NaN NaN NaN
MT_10 0.62 4.29 -1.65 NaN NaN NaN
MT_11 2.44 1.39 3.27 NaN NaN NaN
MT_12 5.10 10.75 1.11 3.44 3.95 3.05
MT_13 -1.34 -3.31 0.28 NaN NaN NaN
AT_09 -1.13 -3.77 0.65 4.13 1.61 6.01
AT_10 -0.32 -0.71 -0.12 -3.36 -7.94 0.08
AT_11 0.86 -0.10 1.76 -0.61 -2.70 1.31
MT_14 -0.06 -3.87 3.45 NaN NaN NaN
AT_12 -3.72 -10.61 3.33 NaN NaN NaN
MT_15 -2.30 -6.42 1.52 NaN NaN NaN
MT_16 3.95 5.70 4.51 NaN NaN NaN
MT_17 -4.34 -4.47 -4.21 -6.23 -9.25 -3.39
MT_18 -2.80 -4.93 -0.91 NaN NaN NaN
AT_13 3.06 -3.37 8.69 NaN NaN NaN
MT_19 0.88 -0.31 1.73 -0.28 -2.92 1.51
MT_20 -0.86 -2.50 0.25 -1.09 -1.93 -0.49
CVT_01 -3.36 -3.73 -2.96 -4.25 -7.84 -1.27
AT_14 -4.44 NaN NaN -2.16 NaN NaN
AT_15 1.21 4.57 -0.72 -0.80 0.25 -0.83
MT_21 1.06 NaN NaN NaN NaN NaN
MT_22 0.04 NaN NaN NaN NaN NaN
MT_23 1.99 -5.80 8.06 1.46 -3.72 5.46
MT_24 -1.63 -1.78 -1.51 NaN NaN NaN
AT_16 -0.69 -3.26 2.42 NaN NaN NaN
AT_17 -1.83 -5.02 1.46 NaN NaN NaN
MT_25 -1.11 -0.41 -1.74 NaN NaN NaN
AT_18 -1.50 -0.08 -2.77 -0.58 -0.95 -0.22
MT_26 -2.88 -4.39 -1.53 NaN NaN NaN
MT_27 0.69 -1.66 2.87 NaN NaN NaN
MT_28 4.07 7.17 3.49 NaN NaN NaN
MT_29 0.63 -2.98 3.89 3.62 3.83 3.23
MT_30 0.54 2.29 -0.70 NaN NaN NaN
AT_19 -3.44 -6.09 -1.57 NaN NaN NaN
AT_20 -3.83 -4.47 -3.44 NaN NaN NaN
MT_31 -1.88 0.96 -3.92 -6.01 -4.82 -6.87
MT_32 -2.66 -7.59 2.13 NaN NaN NaN
AT_21 1.77 -2.40 4.67 -3.14 -7.60 -0.03
AT_22 -1.10 -2.38 0.39 NaN NaN NaN
AT_23 -1.11 -6.54 3.86 NaN NaN NaN
MT_33 NaN NaN NaN 0.53 -0.52 1.12