This was hands down the messiest set of data that I have attempted to manage. The original dataset contained 74 observations across 191 variables, only about half housed any data. The EPA seems to use the same Excel template for the various types of vehicles it tracks, hence a large amount of unused fuel economy and dinosaur drinking engine specs. The formatting of the CSV was also very strange, the names of all of the variables were found on row seven of the dataset, and at the end of each manufacturer’s section, they added the name of the vehicle to its own row at a fixed column interval.


library(tidyverse)
## Loading tidyverse: ggplot2
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag():    dplyr, stats
library(ggrepel)

Load in the data


AKA: Racks on racks of NAs

EV <- read.csv("EVs.csv", header = TRUE, stringsAsFactors = FALSE, na.strings = c("", "NA"))
str(EV)
## 'data.frame':    74 obs. of  191 variables:
##  $ X                                                                                                               : logi  NA NA NA NA NA NA ...
##  $ X2010.and.Later.Electric.Vehicles...data.in.EPA.s.Verify.data.base...plus.all.electric.driving.range.information: chr  NA NA NA NA ...
##  $ X.1                                                                                                             : chr  NA NA NA NA ...
##  $ X.2                                                                                                             : chr  NA NA NA NA ...
##  $ X.3                                                                                                             : chr  NA NA NA NA ...
##  $ X.4                                                                                                             : chr  NA NA NA NA ...
##  $ X.5                                                                                                             : chr  NA NA NA NA ...
##  $ X.6                                                                                                             : chr  "(Not Confidential)" NA NA NA ...
##  $ X.7                                                                                                             : chr  NA NA NA NA ...
##  $ X.8                                                                                                             : chr  NA NA NA NA ...
##  $ X.9                                                                                                             : chr  NA NA NA NA ...
##  $ X.10                                                                                                            : chr  NA NA NA NA ...
##  $ X.11                                                                                                            : chr  NA NA NA NA ...
##  $ X.12                                                                                                            : chr  "D.Good" NA NA NA ...
##  $ X.13                                                                                                            : chr  NA NA NA NA ...
##  $ X.14                                                                                                            : chr  NA NA NA NA ...
##  $ X.15                                                                                                            : chr  NA NA NA NA ...
##  $ X.16                                                                                                            : chr  NA NA NA NA ...
##  $ X.17                                                                                                            : chr  NA NA NA NA ...
##  $ X.18                                                                                                            : chr  NA NA NA NA ...
##  $ X.19                                                                                                            : chr  NA NA NA NA ...
##  $ X.20                                                                                                            : chr  NA NA NA NA ...
##  $ X.21                                                                                                            : chr  NA NA NA NA ...
##  $ X.22                                                                                                            : chr  NA NA NA NA ...
##  $ X.23                                                                                                            : chr  NA NA NA NA ...
##  $ X.24                                                                                                            : chr  NA NA NA NA ...
##  $ X.25                                                                                                            : chr  NA NA NA NA ...
##  $ X.26                                                                                                            : chr  NA NA NA NA ...
##  $ X.27                                                                                                            : chr  NA NA NA NA ...
##  $ X.28                                                                                                            : chr  NA NA NA NA ...
##  $ X.29                                                                                                            : chr  NA NA NA NA ...
##  $ X.30                                                                                                            : chr  NA NA NA NA ...
##  $ X.31                                                                                                            : chr  NA NA NA NA ...
##  $ X.32                                                                                                            : chr  NA NA NA NA ...
##  $ X.33                                                                                                            : chr  NA NA NA NA ...
##  $ X.34                                                                                                            : chr  NA NA NA NA ...
##  $ X.35                                                                                                            : chr  NA NA NA NA ...
##  $ X.36                                                                                                            : chr  NA NA NA NA ...
##  $ X.37                                                                                                            : chr  NA NA NA NA ...
##  $ X.38                                                                                                            : chr  NA NA NA NA ...
##  $ X.39                                                                                                            : chr  NA NA NA NA ...
##  $ X.40                                                                                                            : chr  NA NA NA NA ...
##  $ X.41                                                                                                            : chr  NA NA NA NA ...
##  $ X.42                                                                                                            : chr  NA NA NA NA ...
##  $ X.43                                                                                                            : chr  NA NA NA NA ...
##  $ X.44                                                                                                            : chr  NA NA NA NA ...
##  $ X.45                                                                                                            : chr  NA NA NA NA ...
##  $ X.46                                                                                                            : chr  NA NA NA NA ...
##  $ X.47                                                                                                            : chr  NA NA NA NA ...
##  $ X.48                                                                                                            : chr  NA NA NA NA ...
##  $ X.49                                                                                                            : chr  NA NA NA NA ...
##  $ X.50                                                                                                            : chr  NA NA NA NA ...
##  $ X.51                                                                                                            : chr  NA NA NA NA ...
##  $ X.52                                                                                                            : chr  NA NA NA NA ...
##  $ X.53                                                                                                            : chr  NA NA NA NA ...
##  $ X.54                                                                                                            : chr  NA NA NA NA ...
##  $ X.55                                                                                                            : chr  NA NA NA NA ...
##  $ X.56                                                                                                            : chr  NA NA NA NA ...
##  $ X.57                                                                                                            : chr  NA NA NA NA ...
##  $ X.58                                                                                                            : chr  NA NA NA NA ...
##  $ X.59                                                                                                            : chr  NA NA NA NA ...
##  $ X.60                                                                                                            : chr  NA NA NA NA ...
##  $ X.61                                                                                                            : chr  NA NA NA NA ...
##  $ X.62                                                                                                            : chr  NA NA NA NA ...
##  $ X.63                                                                                                            : chr  NA NA NA NA ...
##  $ X.64                                                                                                            : chr  NA NA NA NA ...
##  $ X.65                                                                                                            : chr  NA NA NA NA ...
##  $ X.66                                                                                                            : chr  NA NA NA NA ...
##  $ X.67                                                                                                            : chr  NA NA NA NA ...
##  $ X.68                                                                                                            : chr  NA NA NA NA ...
##  $ X.69                                                                                                            : chr  NA NA NA NA ...
##  $ X.70                                                                                                            : chr  NA NA NA NA ...
##  $ X.71                                                                                                            : chr  NA NA NA NA ...
##  $ X.72                                                                                                            : chr  NA NA NA NA ...
##  $ X.73                                                                                                            : chr  NA NA NA NA ...
##  $ X.74                                                                                                            : logi  NA NA NA NA NA NA ...
##  $ X.75                                                                                                            : chr  NA NA NA NA ...
##  $ X.76                                                                                                            : chr  NA NA NA NA ...
##  $ X.77                                                                                                            : chr  NA NA NA NA ...
##  $ X.78                                                                                                            : chr  NA NA NA NA ...
##  $ X.79                                                                                                            : chr  NA NA NA NA ...
##  $ X.80                                                                                                            : chr  NA NA NA NA ...
##  $ X.81                                                                                                            : chr  NA NA NA NA ...
##  $ X.82                                                                                                            : chr  NA NA NA NA ...
##  $ X.83                                                                                                            : chr  NA NA NA NA ...
##  $ X.84                                                                                                            : chr  NA NA NA NA ...
##  $ X.85                                                                                                            : chr  NA NA NA NA ...
##  $ X.86                                                                                                            : chr  NA NA NA NA ...
##  $ X.87                                                                                                            : chr  NA NA NA NA ...
##  $ X.88                                                                                                            : chr  NA NA NA NA ...
##  $ X.89                                                                                                            : chr  NA NA NA NA ...
##  $ X.90                                                                                                            : chr  NA NA NA NA ...
##  $ X.91                                                                                                            : chr  NA NA NA NA ...
##  $ X.92                                                                                                            : chr  NA NA NA NA ...
##  $ X.93                                                                                                            : chr  NA NA NA NA ...
##  $ X.94                                                                                                            : chr  NA NA NA NA ...
##  $ X.95                                                                                                            : chr  NA NA NA NA ...
##  $ X.96                                                                                                            : chr  NA NA NA NA ...
##  $ X.97                                                                                                            : chr  NA NA NA NA ...
##   [list output truncated]

Clean the data


AKA: Dplyr and Base collide

colnames(EV) <- EV[7,]
EV <- EV[-1:-7,]
EV <- EV[,-1]
EV <- EV %>% select(`Mfr Name`, `Range1 - Model Type Driving Range - Conventional Fuel`, Carline, `Drive Desc`, `Carline Class Desc`, `Batt Specific Energy (Watt-hr/kg)`) 
EV <- EV %>% na.omit() 
newNames <- c("Make", "Range", "Model", "Drive", "Class", "Watt-Hr/Kg")
colnames(EV) <- newNames

Take a peek at what the data looks like.

str(EV)
## 'data.frame':    33 obs. of  6 variables:
##  $ Make      : chr  "BMW" "BMW" "General Motors" "FCA US LLC" ...
##  $ Range     : chr  "81" "114" "238" "84" ...
##  $ Model     : chr  "I3 BEV (60 Amp-hour battery)" "I3 BEV (94 Amp-hour battery)" "BOLT" "500e" ...
##  $ Drive     : chr  "2-Wheel Drive, Rear" "2-Wheel Drive, Rear" "2-Wheel Drive, Front" "2-Wheel Drive, Front" ...
##  $ Class     : chr  "Subcompact Cars" "Subcompact Cars" "Small Station Wagons" "Minicompact Cars" ...
##  $ Watt-Hr/Kg: chr  "93" "132" "140" "88" ...
##  - attr(*, "na.action")=Class 'omit'  Named int [1:34] 1 3 4 6 7 9 10 13 16 18 ...
##   .. ..- attr(*, "names")= chr [1:34] "8" "10" "11" "13" ...

Headed in the right direction. Time to convert some classes and rename some observations.

EV <- EV %>% mutate_at(vars(Range, `Watt-Hr/Kg`), funs(as.numeric))

EV$Drive[grepl("Front",EV$Drive)] <- "Front"
EV$Drive[grepl("Rear", EV$Drive)] <- "Rear"
EV$Drive[grepl("All", EV$Drive)] <- "AWD"

EV <- EV %>% mutate_at(vars(Drive), funs(as.factor))
EV <- EV %>% distinct(Model, .keep_all = TRUE)

The data should be in decent shape to do something with now…

str(EV)
## 'data.frame':    20 obs. of  6 variables:
##  $ Make      : chr  "BMW" "BMW" "General Motors" "FCA US LLC" ...
##  $ Range     : num  81 114 238 84 115 124 93 87 59 107 ...
##  $ Model     : chr  "I3 BEV (60 Amp-hour battery)" "I3 BEV (94 Amp-hour battery)" "BOLT" "500e" ...
##  $ Drive     : Factor w/ 3 levels "AWD","Front",..: 3 3 2 2 2 2 2 2 3 2 ...
##  $ Class     : chr  "Subcompact Cars" "Subcompact Cars" "Small Station Wagons" "Minicompact Cars" ...
##  $ Watt-Hr/Kg: num  93 132 140 88 110 ...

…looks good enough to plot.


Exploratory plot

A plot looking at the different ranges achieved by each car by brand.

ggplot(EV, aes(Make, Range)) +
  geom_label_repel(aes(label = paste(Model, Range, sep = ": ")), color = "dodgerblue", size = 2) +
  theme_classic() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


Summary

All in all, this was a fun dataset to practice cleaning messy data. There were some challenging methods that I hadn’t used before (i.e. mutate_at and .keep_all), and as a bonus, StackOverflow was down for maintenance which was both a blessing and a curse. On top of gaining some new cleaning skills, this is my first time using RMarkdown which I really liked messing with. I didn’t get too deep into ggplot other than a basic plot because I really wanted to focus on getting a useable data frame that could be explored later.

Data can be found at fueleconomy.gov


Check out more non-sense:

Twitter: Randhyllcho

GitHub: Ryan Christensen