Project 1

Updated by CGG 10/1/24

Description

You have been hired as a consultant by Disney to create a location for a new amusement park. Your job is to analyze weather data from different locations to pick out the best option.

Part 1: Normal data cleanup (5 points)

Begin by looking at the climate normal data. Normal data is the predicted weather for a specific date and location. It is not tied to an individual year.

Load your climate normal datafiles. You will need to do some clean-up. Be sure to look at the data carefully. Below are a list of suggested dplyr activities.

Suggested tasks:

#load libraries
knitr::opts_chunk$set(echo = FALSE, include = TRUE)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.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
library(janitor)
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(lubridate)
library(dplyr)
library(ggplot2)

#fixing titles
#climate

climate_raw <- read_csv('ClimateNormalData_v2.csv',
                        comment = "#",
                        col_names = c("station", "month", "day", "tmax"))
## Rows: 1464 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): station, month, day, tmax
## 
## ℹ 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.
climate <- climate_raw %>% 
  drop_na() %>% 
  slice(-1) %>% 
  mutate(year = 2023) %>% 
  mutate(date_as_text = paste(month, day, year, sep = "/"))

climate <- climate %>% 
  mutate(mdy(date_as_text)) %>% 
  mutate(date = mdy(date_as_text)) %>% 
  mutate(tmax = as.numeric(tmax))
         
  
  
#stations

stations_raw <- read_csv('ClimateNormalData_stations_v2.csv',
                        comment = "#",
                        col_names = c("station", "name", "latitude", "longitude", "elevation"))
## Rows: 7 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): station, name, latitude, longitude, elevation
## 
## ℹ 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.
stations <- stations_raw %>% 
  drop_na() %>% 
  slice(-1)

#joining tables

climate_w_stations <- climate %>% 
  inner_join(stations, by = "station") %>% 
  select(station, name, tmax, date)

Part 2: Summary table (5 points)

Now that you have the data, create some basic summary data. Show a table with the average temperature by month and location. Have the stations as rows, and the month as columns.

Hint: you may need to use dplyr pivot. First group, then summarise, then pivot. You should end up with a table showing the name for each row, and then each month as a column. You may want to use dplyr and lubridate to create a month column.

Summary <- climate_w_stations %>%
  mutate(month = month(date)) %>% 
  group_by(name, month) %>% 
  summarise(avg_temp = mean(tmax)) %>% 
    pivot_wider(names_from = month, values_from = avg_temp)
## `summarise()` has grouped output by 'name'. You can override using the
## `.groups` argument.

Part 3: Best location for amusement park (5 points)

We want to find the best location for an amusement park that isn’t too hot, or too cold.

Define an appropriate temperature range where it is comfortable to be outside. Then, create a graph showing how different locations meet your temperature requirement.

Hint: use mutate to create a new field using ifelse (and some temperature range). Set this value to either 1 (for good) or 0 (for bad). Then look at how much of your dataset falls into this ‘good’ range for each station.

Write a brief 2-3 sentence explanation of your findings.

comfortable_temp <- climate_w_stations %>% 
    mutate(comfortable = if_else(tmax >= 60 & tmax <= 85, 1, 0)) %>% 
             group_by(name) %>% 
  summarise(comfortable_days = sum(comfortable))


ggplot(comfortable_temp) +
  geom_col(mapping = aes(x = name, y = comfortable_days),
           color = 'lemonchiffon',
           fill = 'mistyrose')

# Written Explanation
#
#The chart I decided to make counts how many of the days per year at each station they recorded a temperature within the comfortable range(60-85). This range is the optimal temperature to walk around an amusement park. The Texas station had the best results which makes it the best area to look to put an amusement park

Part 4: Prediction (5 points)

Now, you need to figure out how much the average daily weather for your best site varies from the climate normals for 2023.

Load up the GHCN_daily dataset. You’ll want to filter it down to your chosen site, and then turn the date_as_text column into a proper date. Then, join it to your climate normals (again, filtered to your chosen site) using the date.

Note that tmax is stored as Celsius. You’ll need to convert it.

Create two predictions.

First, compare the actual tmax versus predicted tmax. What is the error? Graph your results and give a 2-3 sentence explanation.

Second, compare the number of days that are predicted to be nice, versus the actual number of days that were nice. Use the same definition as the prior question.

What is the accuracy, precision, and recall of the climate normal data? Give a 2-3 sentence explanation of your results.

ghcn_raw <- read_csv('GHCN_Daily_v2.csv')
## Rows: 88644 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): station, date_as_text
## dbl (1): tmax_actual_in_c
## 
## ℹ 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.
ghcn_clean <- ghcn_raw %>% 
  filter(station == 'USW00013904') %>% 
  mutate(tmax_actual_in_f = (tmax_actual_in_c * (9/5) + 32)) %>%  #formula from standard safari conversion
  mutate(mdy(date_as_text)) %>% 
  mutate(date = mdy(date_as_text)) %>% 
   select(station, tmax_actual_in_f, date)

climate_w_ghcn <- ghcn_clean %>% 
  inner_join(climate_w_stations, by = c("station", "date")) %>%
  select(station, tmax, tmax_actual_in_f, date)

predicted_vs_actual <- mean(climate_w_ghcn$tmax, na.rm = TRUE)
prediction <- function(vector_of_values) {return( c(NA, vector_of_values[-c(length(vector_of_values))]))}
prior1_tmax <- prediction(climate_w_ghcn$tmax)
prior2_tmax <- prediction(prior1_tmax)
prior3_tmax <- prediction(prior2_tmax)

prediction_tmax <- climate_w_ghcn %>%
  mutate(prior1_tmax = prior1_tmax,
         prior3_tmax = prior3_tmax,
         predicted_vs_actual = predicted_vs_actual)

error_predict_vs_actual <- abs(climate_w_ghcn$tmax - climate_w_ghcn$tmax_actual_in_f)
summary(error_predict_vs_actual)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.020   3.280   7.240   7.699  10.360  30.620
hist(error_predict_vs_actual)

#Explanation
#
#there is still a large spread with the max being a 30 degree error but the high concentration is within 1-10 degrees of error which does show a good correlation. I think the 3 day prediction is where most of the wider range of numbers came from.
#second prediction

comfortable_temp <- climate_w_ghcn %>% 
  filter(station == 'USW00013904') %>%  
    mutate(comfortable = if_else(tmax >= 60 & tmax <= 85, 1, 0)) %>% 
  summarise(comfortable_days = sum(comfortable))
 
print(comfortable_temp)
## # A tibble: 1 × 1
##   comfortable_days
##              <dbl>
## 1              209
comfortable_temp_actual <- climate_w_ghcn %>% 
  filter(station == 'USW00013904') %>% 
  mutate(comfortable_a = if_else(tmax_actual_in_f >= 60 & tmax_actual_in_f <= 85, 1, 0)) %>% 
  summarise(comfortable_days_a = sum(comfortable_a))

print(comfortable_temp_actual)
## # A tibble: 1 × 1
##   comfortable_days_a
##                <dbl>
## 1                177
#Explanation
#
#The error was by 32 in the predicted vs actual "nice days". this is good for showing the prospective good locations but not fully accurate. the normal climate data is good but not exact to the actual numbers as both predictions had errors.