Cars: Engine Performance and Fuel Efficiency

Author

George Bothos

Introduction

This project is going to explore the relationship between the performance of the engine and the fuel efficiency, and it’s going to be using the cars dataset from the CORGIS repository. The data is originally coming from the U.S. Department of Energy and the Environmental Protection Agency (EPA), and it contains information on 5,076 vehicles across 18 variables.

The quantitative variables that I will be focusing on and examining are horsepower, which is measuring the engine power, and highway miles per gallon (MPG), which measures how efficiently a vehicle is using fuel while driving on highways. I’m also going to be using a driveline type, a categorical variable that distinguishes between different drivetrain configurations, such as front-wheel drive, rear-wheel drive, and all-wheel drive.

The research question that I am asking is: How does engine horsepower relate to highway fuel efficiency, and how does this relationship differ across drive line types? My plan is to look at this relationship using data visualizations and linear regression analysis to see whether horsepower is a useful predictor of highway MPG.

Dataset: CORGIS Cars Dataset

Original Data Source: U.S. Department of Energy and Environmental Protection Agency (EPA)

Loading the tidyverse package for working with and visualizing data

# Load the tidyverse package for data analysis and visualization
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.3     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Importing the Cars dataset using the required read_csv() function

# Import the Cars dataset from the CSV file
cars <- readr::read_csv("cars (1).csv")
Rows: 5076 Columns: 18
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (8): Engine Information.Driveline, Engine Information.Engine Type, Engin...
dbl (9): Dimensions.Height, Dimensions.Length, Dimensions.Width, Engine Info...
lgl (1): Engine Information.Hybrid

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Exploring the dataset

# Preview the data, identify the variables, and examine their data types
head(cars)
# A tibble: 6 × 18
  Dimensions.Height Dimensions.Length Dimensions.Width Engine Information.Driv…¹
              <dbl>             <dbl>            <dbl> <chr>                    
1               140               143              202 All-wheel drive          
2               140               143              202 Front-wheel drive        
3               140               143              202 Front-wheel drive        
4               140               143              202 All-wheel drive          
5               140               143              202 All-wheel drive          
6                91                17               62 All-wheel drive          
# ℹ abbreviated name: ¹​`Engine Information.Driveline`
# ℹ 14 more variables: `Engine Information.Engine Type` <chr>,
#   `Engine Information.Hybrid` <lgl>,
#   `Engine Information.Number of Forward Gears` <dbl>,
#   `Engine Information.Transmission` <chr>, `Fuel Information.City mpg` <dbl>,
#   `Fuel Information.Fuel Type` <chr>, `Fuel Information.Highway mpg` <dbl>,
#   Identification.Classification <chr>, Identification.ID <chr>, …
names(cars)
 [1] "Dimensions.Height"                              
 [2] "Dimensions.Length"                              
 [3] "Dimensions.Width"                               
 [4] "Engine Information.Driveline"                   
 [5] "Engine Information.Engine Type"                 
 [6] "Engine Information.Hybrid"                      
 [7] "Engine Information.Number of Forward Gears"     
 [8] "Engine Information.Transmission"                
 [9] "Fuel Information.City mpg"                      
[10] "Fuel Information.Fuel Type"                     
[11] "Fuel Information.Highway mpg"                   
[12] "Identification.Classification"                  
[13] "Identification.ID"                              
[14] "Identification.Make"                            
[15] "Identification.Model Year"                      
[16] "Identification.Year"                            
[17] "Engine Information.Engine Statistics.Horsepower"
[18] "Engine Information.Engine Statistics.Torque"    
str(cars)
spc_tbl_ [5,076 × 18] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ Dimensions.Height                              : num [1:5076] 140 140 140 140 140 91 91 201 201 147 ...
 $ Dimensions.Length                              : num [1:5076] 143 143 143 143 143 17 17 221 221 96 ...
 $ Dimensions.Width                               : num [1:5076] 202 202 202 202 202 62 62 191 191 34 ...
 $ Engine Information.Driveline                   : chr [1:5076] "All-wheel drive" "Front-wheel drive" "Front-wheel drive" "All-wheel drive" ...
 $ Engine Information.Engine Type                 : chr [1:5076] "Audi 3.2L 6 cylinder 250hp 236ft-lbs" "Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo" "Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo" "Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo" ...
 $ Engine Information.Hybrid                      : logi [1:5076] TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ Engine Information.Number of Forward Gears     : num [1:5076] 6 6 6 6 6 6 6 6 6 6 ...
 $ Engine Information.Transmission                : chr [1:5076] "6 Speed Automatic Select Shift" "6 Speed Automatic Select Shift" "6 Speed Manual" "6 Speed Automatic Select Shift" ...
 $ Fuel Information.City mpg                      : num [1:5076] 18 22 21 21 21 16 17 13 14 22 ...
 $ Fuel Information.Fuel Type                     : chr [1:5076] "Gasoline" "Gasoline" "Gasoline" "Gasoline" ...
 $ Fuel Information.Highway mpg                   : num [1:5076] 25 28 30 28 28 27 26 18 20 30 ...
 $ Identification.Classification                  : chr [1:5076] "Automatic transmission" "Automatic transmission" "Manual transmission" "Automatic transmission" ...
 $ Identification.ID                              : chr [1:5076] "2009 Audi A3 3.2" "2009 Audi A3 2.0 T AT" "2009 Audi A3 2.0 T" "2009 Audi A3 2.0 T Quattro" ...
 $ Identification.Make                            : chr [1:5076] "Audi" "Audi" "Audi" "Audi" ...
 $ Identification.Model Year                      : chr [1:5076] "2009 Audi A3" "2009 Audi A3" "2009 Audi A3" "2009 Audi A3" ...
 $ Identification.Year                            : num [1:5076] 2009 2009 2009 2009 2009 ...
 $ Engine Information.Engine Statistics.Horsepower: num [1:5076] 250 200 200 200 200 265 265 350 280 211 ...
 $ Engine Information.Engine Statistics.Torque    : num [1:5076] 236 207 207 207 207 243 243 325 266 258 ...
 - attr(*, "spec")=
  .. cols(
  ..   Dimensions.Height = col_double(),
  ..   Dimensions.Length = col_double(),
  ..   Dimensions.Width = col_double(),
  ..   `Engine Information.Driveline` = col_character(),
  ..   `Engine Information.Engine Type` = col_character(),
  ..   `Engine Information.Hybrid` = col_logical(),
  ..   `Engine Information.Number of Forward Gears` = col_double(),
  ..   `Engine Information.Transmission` = col_character(),
  ..   `Fuel Information.City mpg` = col_double(),
  ..   `Fuel Information.Fuel Type` = col_character(),
  ..   `Fuel Information.Highway mpg` = col_double(),
  ..   Identification.Classification = col_character(),
  ..   Identification.ID = col_character(),
  ..   Identification.Make = col_character(),
  ..   `Identification.Model Year` = col_character(),
  ..   Identification.Year = col_double(),
  ..   `Engine Information.Engine Statistics.Horsepower` = col_double(),
  ..   `Engine Information.Engine Statistics.Torque` = col_double()
  .. )
 - attr(*, "problems")=<pointer: 0x0000018c0f4fff80> 

Cleaning the dataset

# Rename important variables to make them easier to use in the analysis
cars_clean <- cars %>%
  rename(
    horsepower = `Engine Information.Engine Statistics.Horsepower`,
    torque = `Engine Information.Engine Statistics.Torque`,
    highway_mpg = `Fuel Information.Highway mpg`,
    city_mpg = `Fuel Information.City mpg`,
    driveline = `Engine Information.Driveline`
  )

Checking and Examining the dataset

# Check for missing values, identify driveline types, and preview the cleaned data
colSums(is.na(cars_clean))
                         Dimensions.Height 
                                         0 
                         Dimensions.Length 
                                         0 
                          Dimensions.Width 
                                         0 
                                 driveline 
                                         0 
            Engine Information.Engine Type 
                                         0 
                 Engine Information.Hybrid 
                                         0 
Engine Information.Number of Forward Gears 
                                         0 
           Engine Information.Transmission 
                                         0 
                                  city_mpg 
                                         0 
                Fuel Information.Fuel Type 
                                         0 
                               highway_mpg 
                                         0 
             Identification.Classification 
                                         0 
                         Identification.ID 
                                         0 
                       Identification.Make 
                                         0 
                 Identification.Model Year 
                                         0 
                       Identification.Year 
                                         0 
                                horsepower 
                                         0 
                                    torque 
                                         0 
unique(cars_clean$driveline)
[1] "All-wheel drive"   "Front-wheel drive" "Rear-wheel drive" 
[4] "Four-wheel drive" 
head(cars_clean)
# A tibble: 6 × 18
  Dimensions.Height Dimensions.Length Dimensions.Width driveline        
              <dbl>             <dbl>            <dbl> <chr>            
1               140               143              202 All-wheel drive  
2               140               143              202 Front-wheel drive
3               140               143              202 Front-wheel drive
4               140               143              202 All-wheel drive  
5               140               143              202 All-wheel drive  
6                91                17               62 All-wheel drive  
# ℹ 14 more variables: `Engine Information.Engine Type` <chr>,
#   `Engine Information.Hybrid` <lgl>,
#   `Engine Information.Number of Forward Gears` <dbl>,
#   `Engine Information.Transmission` <chr>, city_mpg <dbl>,
#   `Fuel Information.Fuel Type` <chr>, highway_mpg <dbl>,
#   Identification.Classification <chr>, Identification.ID <chr>,
#   Identification.Make <chr>, `Identification.Model Year` <chr>, …

Initial Linear Regression Analysis (Before Data Correction)

# Create the initial regression model and examine its results and diagnostic plots
cars_model <- lm(highway_mpg ~ horsepower, data = cars_clean)
summary(cars_model)

Call:
lm(formula = highway_mpg ~ horsepower, data = cars_clean)

Residuals:
    Min      1Q  Median      3Q     Max 
-13.824  -3.026   0.198   3.243 201.170 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) 34.2220194  0.2292682  149.27   <2e-16 ***
horsepower  -0.0373255  0.0007994  -46.69   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 5.427 on 5074 degrees of freedom
Multiple R-squared:  0.3005,    Adjusted R-squared:  0.3004 
F-statistic:  2180 on 1 and 5074 DF,  p-value: < 2.2e-16
plot(cars_model)

Investigating the outlier

# Investigate an unusually high highway MPG value and compare it to the dataset
cars_clean[3687, c("horsepower", "highway_mpg", "driveline")]
# A tibble: 1 × 3
  horsepower highway_mpg driveline       
       <dbl>       <dbl> <chr>           
1        332         223 Rear-wheel drive
summary(cars_clean$highway_mpg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  11.00   20.00   24.00   24.13   28.00  223.00 

Final Linear Regression Analysis (After Data Correction)

# Correct the 223 MPG data-entry error to 23 MPG based on EPA information
cars_clean$highway_mpg[3687] <- 23
# Rerun the regression and diagnostic plots using the corrected dataset
cars_model <- lm(highway_mpg ~ horsepower, data = cars_clean)
summary(cars_model)

Call:
lm(formula = highway_mpg ~ horsepower, data = cars_clean)

Residuals:
     Min       1Q   Median       3Q      Max 
-13.7965  -3.0145   0.2111   3.2637  14.0081 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) 34.2548142  0.1957701  174.97   <2e-16 ***
horsepower  -0.0375924  0.0006826  -55.07   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 4.634 on 5074 degrees of freedom
Multiple R-squared:  0.3741,    Adjusted R-squared:  0.374 
F-statistic:  3033 on 1 and 5074 DF,  p-value: < 2.2e-16
plot(cars_model)

Regression Interpretation

What we can see from the linear regression analysis is that there’s actually a statistically significant negative relationship between horsepower and highway fuel efficiency. The regression equation is

Highway MPG = 34.2548 - 0.03759(Horsepower)

The coefficient in front of horsepower is showing us that every additional 100 horsepower is associated with approximately 3.76 fewer highway MPG on average. We see that the p-value is less than 0.05, which shows us that the relationship is statistically significant. Furthermore, the adjusted R-squared value is 0.3740, suggesting to us that horsepower explains approximately 37.4% of the variation in highway fuel efficiency.

Also, if we look at the diagnostic plot, we can see that the model does have some limitations. The residuals versus fitted plot showed us a curved pattern, which suggests that the relationship may not be completely linear as we thought. The QQ plot follows the expected line fairly closely, although there do appear to be some deviations near the ends. The scale location plot suggests that the residuals do not have perfectly constant variance. Overall, what we can see is that horsepower is a useful predictor of highway MPG, but there are a lot of other factors that are likely influencing fuel efficiency as well.

Creating the Main Visualization

# Visualize horsepower and highway MPG using four colors for driveline types
ggplot(cars_clean, aes(x = horsepower, y = highway_mpg, color = driveline)) +
  geom_point(alpha = 0.5) +
  scale_color_manual(values = c(
    "All-wheel drive" = "#2563EB",
    "Front-wheel drive" = "#16A34A",
    "Rear-wheel drive" = "#DC2626",
    "Four-wheel drive" = "#9333EA"
  )) +
  theme_minimal() +
  labs(
    title = "Horsepower vs. Highway Fuel Efficiency",
    subtitle = "Comparing vehicles across four driveline types",
    x = "Engine Horsepower (HP)",
    y = "Highway Fuel Efficiency (MPG)",
    color = "Driveline Type",
    caption = "Source: U.S. Department of Energy and EPA, via CORGIS Cars Dataset"
  )

Final Analysis and Reflection

For this project, I began by exploring the cars dataset and examining the different variables and their data types. I then proceeded to clean the dataset by renaming several columns, including horsepower, highway MPG, city MPG, torque, and driveline, so that it was easier for me to work with them in R Studio. I also made sure to check and see if there were any missing values, but I did not find any. While I was doing my regression analysis, I did discover an unusual observation showing 223 highway MPG for a Chevrolet Silverado Hybrid. After checking published EPA fuel economy information, I corrected this value to 23 MPG so that it would not distort the analysis that I was creating.

EPA Reference: https://carsandracingstuff.com/library/f/fueleconomyguide2011.pdf

The scatter plot I created is comparing engine horsepower and highway fuel efficiency, and it’s using four different colors to show us the difference between the different driveline types. Overall, the visualization is showing us that the vehicles with higher horsepower tend to have a lower highway MPG. The front-wheel drive vehicles generally do have better fuel efficiency and lower horsepower, while the rear-wheel drive vehicles have a lot of the highest horsepower models. This pattern actually did support my regression results, which showed a statistically significant negative relationship between horsepower and highway MPG. However, when we take a look at the adjusted R-squared value of 0.3740, we see that the horsepower alone did not explain all differences in the fuel efficiency of the cars.

One thing that I do believe I would have liked to explore further is how the other engine characteristics, such as torque or the number of forward gears, are also influencing fuel efficiency. I think it would be interesting to create separate regression models for each driveline type to compare the relationships a little more closely than I did today. This would provide me with a better understanding of whether horsepower has a similar relationship with fuel efficiency across different types of vehicles.