EV Cost of Driving and Energy Efficiency
Given a cost of electricity (dollars per kilowatt-hour) the cost trips taken with an electric vehicle can be calculated
Utilizing average energy pricing (available at, for example https://www.eia.gov/electricity/data/state/ at a national level or determining location-specific pricing, for example DTE in the Detroit area: https://solutions.dteenergy.com/dte/en/Products/Time-of-Day-3-p-m---7-p-m-/p/TOD-3-7) or a user-inputted price of energy per kilowatt-hour, the cost of driving can be calculated. This can be used to help determine the total cost of ownership for electric vehicles.
For the below examples, the average pricing per state, per month are utilized. However, this does not take time of day pricing into consideration. A user can optionally input the average price per kilowatt-hour they pay for electricity or use the state-wide average price per month. Further below, a user can input the time of day pricing to show the impact of charging their vehicle on- or off-peak.
Using the calculate_charging_sessions method in the code appendix below on this page (similar to the method in EV Charger Power, but just two lines to capture first and last odometer readings during charging sessions has been added).
Additionally, to convert soc (state of charge) into kilowatt-hours, the capacity of the battery must be known as well. The batteryCapacity for many models and model year Teslas is given in EV Charger Power.
Note that if any charging sessions are missed in the source data, the odometer change for the charging sessions after a missed charging session will not make sense with the charge added. For example, if the odometer reads 10,000 miles at charging session A, which ended at 0.85 soc, then 10,800 miles at charging session B, which started at 0.35 soc, where the vehicle has a battery capacity of 75 kwh, that would imply the vehicle drove 800 miles with 37.5 kwh, which is not realistic. Most likely, one or more charging sessions occurred between charging session A and B.
This code will calculate cost per mile (dollars per mile, as well as cents per mile, for scaling) as well as the miles per gallon equivalent (i.e. the distance the electric vehicle drove when using 33.7 kwh of energy, which is the amount of energy in one gallon of gasoline). Note that for level 3 charges, the cost should generally be known from the charger (and will probably exceed the residential price for the energy) and the efficiency is around 94% (meaning for every 1 kilowatt-hour sent from the charger, 0.94 kilowatt-hours reach the battery), for level 2 charges, the efficiency is around 90% (meaning for every 1 kilowatt-hour sent from the grid, 0.90 kilowatt-hours reach the battery), and for level 1 charges, the efficiency is around 80% (meaning for every 1 kilowatt-hour sent from the grid, 0.80 kilowatt-hours reach the battery).
charging_df = calculate_charging_sessions(df, urban, states, counties, bat_capacity)
charging_df['Charger_Level'] = pd.cut(charging_df['kw_est'], bins = [0,2.5,30,np.Inf], labels = ['Level_1','Level_2','Level_3'])
charging_df['efficiency'] = charging_df['Charger_Level'].replace(['Level_1', 'Level_2','Level_3'],[0.8, 0.9, 0.94])
charging_df['month_year'] = charging_df['first_time'].map(lambda x: x.strftime('%B %Y'))
charging_df = charging_df.loc[(charging_df['kwh_est'] > 0)]
# If more specific pricing is not given, the average price per state per month can be used as here. (The data can be downloaded from https://www.eia.gov/electricity/monthly/)
# If more specific pricing is available, the column 'cost_per_kwh' should be populated with the cost of a single kilowatt-hour of energy
folder = 'august2023'
state_price = pd.read_excel(f'./Data/Energy_Prices_eia_gov/{folder}/Table_5_06_A.xlsx')
state_price.columns = state_price.iloc[2]
state_price = state_price.iloc[3:-1,0:3].reset_index(drop = True)
state_price = states[['NAME','STUSPS']].merge(state_price, left_on = 'NAME', right_on = 'Census Division\nand State')
charging_df = charging_df.merge(state_price, left_on = 'state', right_on = 'STUSPS')
charging_df['cost_per_kwh'] = charging_df.apply(lambda row: row[row['month_year']]/100, axis=1)
charging_df = charging_df.drop(columns = state_price.columns.tolist())
charging_df = charging_df.sort_values('first_time').reset_index(drop = True)
charging_df = charging_df.loc[charging_df['net_charge_added'] > 0]
charging_df['km_driven_since_last_charge'] = charging_df['start_odometer'].diff()
charging_df['mi_driven_since_last_charge'] = charging_df['km_driven_since_last_charge'] * 0.621371
charging_df['soc_used_since_last_charge'] = charging_df['end_soc'].shift(1) - charging_df['start_soc']
charging_df['kwh_used_since_last_charge'] = charging_df['soc_used_since_last_charge']*bat_capacity
charging_df['mi_per_kwh'] = charging_df['mi_driven_since_last_charge'] / charging_df['kwh_used_since_last_charge']
charging_df['MPGe'] = charging_df['mi_per_kwh']*33.7
charging_df['USD_per_mile'] = ((charging_df['kwh_used_since_last_charge']*charging_df['cost_per_kwh']) / charging_df['mi_driven_since_last_charge'])/ (charging_df['efficiency'].astype(float))
charging_df['cents_per_mile'] = 100*charging_df['USD_per_mile']
charging_df = charging_df.loc[(charging_df['soc_used_since_last_charge'] > 0) & (charging_df['MPGe'] < 250) & (charging_df['mi_driven_since_last_charge'] > 0)].reset_index(drop = True)With this code, the charging sessions for an example vehicle are identified and metadata on the charging sessions can be calculated.

To create the below histograms, the following code can be used



For reference, if a gallon of gas costs $4.00 (400 cents) and a vehicle gets 25 miles to the gallon, the cost per mile driven is 16 cents per mile.
Additionally, a Sankey Diagram can be generated using matplotlib:
Which generates the following flow diagram (Sankey Diagram)

Code Appendix
Last updated