Project 1
Updated by NDG 2/7/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: Data cleanup (5 points)
Begin by looking at the documentation for the climate normal
data.
Then load your ClimateNormalData.csv datafile. 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 both csv files as raw data
- Cleanup the data
- Turn all character date fields into integers
- Create a new string with paste or paste0 that has m/d/y (use 2024
for year)
- Use mdy from lubridate to create an actual date column
- Remove any fields you don’t want to use
- Join the two tables together to get the titles for each
station.
library(tidyverse)
library(lubridate)
library(dplyr)
library(janitor)
t_raw <- read_csv("ClimateNormalData.csv", skip = 3, na = c('', ' ', 'NA', '-1'))
Rows: 35040 Columns: 57── Column specification ───────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): STATION, month, day, hour
dbl (52): HLY-TEMP-NORMAL, years_HLY-TEMP-NORMAL, HLY-TEMP-10PCTL, years_HLY-TEMP-10PCTL, HLY-TEMP-90PCTL, year...
lgl (1): meas_flag_HLY-DEWP-10PCTL
ℹ 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.
janitor::clean_names(t_raw)
print(t_raw)
t_raw_stations <- read_csv("ClimateNormalData_stations.csv", skip = 2)
Rows: 4 Columns: 5── Column specification ───────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): STATION, NAME
dbl (3): 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.
janitor::clean_names(t_raw_stations)
print(t_raw_stations)
NA
NA
library(tidyverse)
library(lubridate)
library(dplyr)
date_as_text <- '2014'
date_as_integer <- as.integer(date_as_text)
date_as_really_long_text <- paste('1', '1', date_as_integer, sep = '/')
date_as_date <- mdy(date_as_really_long_text)
t_joined <- inner_join(t_raw, t_raw_stations, by = "STATION") %>%
rename(mean_temp = "HLY-TEMP-NORMAL")
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.
library(tidyverse)
library(lubridate)
library(dplyr)
t_avg_temp <- t_joined %>%
select(month, STATION, NAME, mean_temp) %>%
group_by(month) %>%
arrange(month) %>%
pivot_wider(names_from = month, values_from = mean_temp)
Warning: Values from `mean_temp` are not uniquely identified; output will contain list-cols.
• Use `values_fn = list` to suppress this warning.
• Use `values_fn = {summary_fun}` to summarise duplicates.
• Use the following dplyr code to identify duplicates.
{data} %>%
dplyr::group_by(STATION, NAME, month) %>%
dplyr::summarise(n = dplyr::n(), .groups = "drop") %>%
dplyr::filter(n > 1L)
View(t_avg_temp)
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.
library(tidyverse)
library(dplyr)
library(ggplot2)
ideal_temp_range <- t_joined %>%
filter(mean_temp > 60, mean_temp < 80)
ggplot(data = t_joined) +
geom_boxplot(mapping = aes(x = NAME, y = mean_temp))

## Austin, TX meets the ideal temperature range the closest as shown by the box plot. I chose between 60 and 80 degrees Fahrenheit as the ideal range because to me that is the best temperature range to be outside. Austin also consistently has the highest temperatures, which may not be ideal for comfort but is better than cold temperatures because rides can still operate in warm weather.
Write a brief 2-3 sentence explanation of your findings.
Part 4: Airport (5 points)
Which of the sites would be best as an airport? Explore the others
variables in your dataset. For example, look at cloud cover or average
wind speed. This may require some data clean, so carefully look at your
dataset for weird values.
Give a chart, and write a 2-3 sentence explanation of your
answer.
library(tidyverse)
library(dplyr)
library(ggplot2)
library(esquisse)
ggplot(t_joined) +
aes(x = NAME, y = `HLY-WIND-AVGSPD`) +
geom_boxplot(fill = "#112446") +
theme_minimal() +
ylim(0, 15)

## JUNEAU INTL AP, AK appears to have a slightly lower average wind speed so it would be best for an airport. High winds would be a significant factor in selecting where to place an airport, as you want a location that is easy to access via plane.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIFByb2plY3QgMQ0KKlVwZGF0ZWQgYnkgTkRHIDIvNy8yNCoNCg0KIyMgRGVzY3JpcHRpb24NCg0KWW91IGhhdmUgYmVlbiBoaXJlZCBhcyBhIGNvbnN1bHRhbnQgYnkgRGlzbmV5IHRvIGNyZWF0ZSBhIGxvY2F0aW9uIGZvciBhIG5ldyBhbXVzZW1lbnQgcGFyay4gWW91ciBqb2IgaXMgdG8gYW5hbHl6ZSB3ZWF0aGVyIGRhdGEgZnJvbSBkaWZmZXJlbnQgbG9jYXRpb25zIHRvIHBpY2sgb3V0IHRoZSBiZXN0IG9wdGlvbi4NCg0KDQojIFBhcnQgMTogRGF0YSBjbGVhbnVwICg1IHBvaW50cykNCg0KQmVnaW4gYnkgbG9va2luZyBhdCB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgdGhlIGNsaW1hdGUgbm9ybWFsIGRhdGEuIA0KDQpUaGVuIGxvYWQgeW91ciBDbGltYXRlTm9ybWFsRGF0YS5jc3YgZGF0YWZpbGUuIFlvdSB3aWxsIG5lZWQgdG8gZG8gc29tZSBjbGVhbi11cC4gQmUgc3VyZSB0byBsb29rIGF0IHRoZSBkYXRhIGNhcmVmdWxseS4gQmVsb3cgYXJlIGEgbGlzdCBvZiBzdWdnZXN0ZWQgZHBseXIgYWN0aXZpdGllcy4NCg0KU3VnZ2VzdGVkIHRhc2tzOg0KDQotIExvYWQgYm90aCBjc3YgZmlsZXMgYXMgcmF3IGRhdGENCi0gQ2xlYW51cCB0aGUgZGF0YQ0KIC0gVHVybiBhbGwgY2hhcmFjdGVyIGRhdGUgZmllbGRzIGludG8gaW50ZWdlcnMNCiAtIENyZWF0ZSBhIG5ldyBzdHJpbmcgd2l0aCBwYXN0ZSBvciBwYXN0ZTAgdGhhdCBoYXMgbS9kL3kgKHVzZSAyMDI0IGZvciB5ZWFyKQ0KIC0gVXNlIG1keSBmcm9tIGx1YnJpZGF0ZSB0byBjcmVhdGUgYW4gYWN0dWFsIGRhdGUgY29sdW1uDQogLSBSZW1vdmUgYW55IGZpZWxkcyB5b3UgZG9uJ3Qgd2FudCB0byB1c2UNCi0gSm9pbiB0aGUgdHdvIHRhYmxlcyB0b2dldGhlciB0byBnZXQgdGhlIHRpdGxlcyBmb3IgZWFjaCBzdGF0aW9uLg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoamFuaXRvcikNCg0KdF9yYXcgPC0gcmVhZF9jc3YoIkNsaW1hdGVOb3JtYWxEYXRhLmNzdiIsIHNraXAgPSAzLCBuYSA9IGMoJycsICcgJywgJ05BJywgJy0xJykpDQpqYW5pdG9yOjpjbGVhbl9uYW1lcyh0X3JhdykNCnByaW50KHRfcmF3KQ0KDQp0X3Jhd19zdGF0aW9ucyA8LSByZWFkX2NzdigiQ2xpbWF0ZU5vcm1hbERhdGFfc3RhdGlvbnMuY3N2Iiwgc2tpcCA9IDIpDQpqYW5pdG9yOjpjbGVhbl9uYW1lcyh0X3Jhd19zdGF0aW9ucykNCnByaW50KHRfcmF3X3N0YXRpb25zKQ0KDQoNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoZHBseXIpDQpkYXRlX2FzX3RleHQgPC0gJzIwMTQnDQpkYXRlX2FzX2ludGVnZXIgPC0gYXMuaW50ZWdlcihkYXRlX2FzX3RleHQpDQpkYXRlX2FzX3JlYWxseV9sb25nX3RleHQgPC0gcGFzdGUoJzEnLCAnMScsIGRhdGVfYXNfaW50ZWdlciwgc2VwID0gJy8nKQ0KDQpkYXRlX2FzX2RhdGUgPC0gbWR5KGRhdGVfYXNfcmVhbGx5X2xvbmdfdGV4dCkNCg0KdF9qb2luZWQgPC0gaW5uZXJfam9pbih0X3JhdywgdF9yYXdfc3RhdGlvbnMsIGJ5ID0gIlNUQVRJT04iKSAlPiUgDQogIHJlbmFtZShtZWFuX3RlbXAgPSAiSExZLVRFTVAtTk9STUFMIikNCg0KDQpgYGANCiMgUGFydCAyOiBTdW1tYXJ5IHRhYmxlICg1IHBvaW50cykNCg0KTm93IHRoYXQgeW91IGhhdmUgdGhlIGRhdGEsIGNyZWF0ZSBzb21lIGJhc2ljIHN1bW1hcnkgZGF0YS4gU2hvdyBhIHRhYmxlIHdpdGggdGhlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUgYnkgbW9udGggYW5kIGxvY2F0aW9uLiBIYXZlIHRoZSBzdGF0aW9ucyBhcyByb3dzLCBhbmQgdGhlIG1vbnRoIGFzIGNvbHVtbnMuDQoNCkhpbnQ6IHlvdSBtYXkgbmVlZCB0byB1c2UgZHBseXIgcGl2b3QuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoZHBseXIpDQoNCg0KdF9hdmdfdGVtcCA8LSB0X2pvaW5lZCAlPiUgDQogIHNlbGVjdChtb250aCwgU1RBVElPTiwgTkFNRSwgbWVhbl90ZW1wKSAlPiUNCiAgZ3JvdXBfYnkobW9udGgpICU+JSANCiAgYXJyYW5nZShtb250aCkgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aCwgdmFsdWVzX2Zyb20gPSBtZWFuX3RlbXApDQoNClZpZXcodF9hdmdfdGVtcCkNCg0KYGBgDQoNCg0KDQojIFBhcnQgMzogQmVzdCBsb2NhdGlvbiBmb3IgYW11c2VtZW50IHBhcmsgKDUgcG9pbnRzKQ0KDQpXZSB3YW50IHRvIGZpbmQgdGhlIGJlc3QgbG9jYXRpb24gZm9yIGFuIGFtdXNlbWVudCBwYXJrIHRoYXQgaXNuJ3QgdG9vIGhvdCwgb3IgdG9vIGNvbGQuDQpEZWZpbmUgYW4gYXBwcm9wcmlhdGUgdGVtcGVyYXR1cmUgcmFuZ2Ugd2hlcmUgaXQgaXMgY29tZm9ydGFibGUgdG8gYmUgb3V0c2lkZS4gVGhlbiwgY3JlYXRlIGEgZ3JhcGggc2hvd2luZyBob3cgZGlmZmVyZW50IGxvY2F0aW9ucyBtZWV0IHlvdXIgdGVtcGVyYXR1cmUgcmVxdWlyZW1lbnQuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQppZGVhbF90ZW1wX3JhbmdlIDwtIHRfam9pbmVkICU+JQ0KICBmaWx0ZXIobWVhbl90ZW1wID4gNjAsIG1lYW5fdGVtcCA8IDgwKQ0KDQpnZ3Bsb3QoZGF0YSA9IHRfam9pbmVkKSArDQogIGdlb21fYm94cGxvdChtYXBwaW5nID0gYWVzKHggPSBOQU1FLCB5ID0gbWVhbl90ZW1wKSkNCg0KIyMgQXVzdGluLCBUWCBtZWV0cyB0aGUgaWRlYWwgdGVtcGVyYXR1cmUgcmFuZ2UgdGhlIGNsb3Nlc3QgYXMgc2hvd24gYnkgdGhlIGJveCBwbG90LiBJIGNob3NlIGJldHdlZW4gNjAgYW5kIDgwIGRlZ3JlZXMgRmFocmVuaGVpdCBhcyB0aGUgaWRlYWwgcmFuZ2UgYmVjYXVzZSB0byBtZSB0aGF0IGlzIHRoZSBiZXN0IHRlbXBlcmF0dXJlIHJhbmdlIHRvIGJlIG91dHNpZGUuIEF1c3RpbiBhbHNvIGNvbnNpc3RlbnRseSBoYXMgdGhlIGhpZ2hlc3QgdGVtcGVyYXR1cmVzLCB3aGljaCBtYXkgbm90IGJlIGlkZWFsIGZvciBjb21mb3J0IGJ1dCBpcyBiZXR0ZXIgdGhhbiBjb2xkIHRlbXBlcmF0dXJlcyBiZWNhdXNlIHJpZGVzIGNhbiBzdGlsbCBvcGVyYXRlIGluIHdhcm0gd2VhdGhlci4NCmBgYA0KDQoNCldyaXRlIGEgYnJpZWYgMi0zIHNlbnRlbmNlIGV4cGxhbmF0aW9uIG9mIHlvdXIgZmluZGluZ3MuDQoNCg0KDQojIFBhcnQgNDogQWlycG9ydCAoNSBwb2ludHMpDQoNCldoaWNoIG9mIHRoZSBzaXRlcyB3b3VsZCBiZSBiZXN0IGFzIGFuIGFpcnBvcnQ/IEV4cGxvcmUgdGhlIG90aGVycyB2YXJpYWJsZXMgaW4geW91ciBkYXRhc2V0LiBGb3IgZXhhbXBsZSwgbG9vayBhdCBjbG91ZCBjb3ZlciBvciBhdmVyYWdlIHdpbmQgc3BlZWQuIFRoaXMgbWF5IHJlcXVpcmUgc29tZSBkYXRhIGNsZWFuLCBzbyBjYXJlZnVsbHkgbG9vayBhdCB5b3VyIGRhdGFzZXQgZm9yIHdlaXJkIHZhbHVlcy4NCg0KR2l2ZSBhIGNoYXJ0LCBhbmQgd3JpdGUgYSAyLTMgc2VudGVuY2UgZXhwbGFuYXRpb24gb2YgeW91ciBhbnN3ZXIuDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShlc3F1aXNzZSkNCg0KZ2dwbG90KHRfam9pbmVkKSArDQogIGFlcyh4ID0gTkFNRSwgeSA9IGBITFktV0lORC1BVkdTUERgKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gIiMxMTI0NDYiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHlsaW0oMCwgMTUpDQoNCiMjIAlKVU5FQVUgSU5UTCBBUCwgQUsgYXBwZWFycyB0byBoYXZlIGEgc2xpZ2h0bHkgbG93ZXIgYXZlcmFnZSB3aW5kIHNwZWVkIHNvIGl0IHdvdWxkIGJlIGJlc3QgZm9yIGFuIGFpcnBvcnQuIEhpZ2ggd2luZHMgd291bGQgYmUgYSBzaWduaWZpY2FudCBmYWN0b3IgaW4gc2VsZWN0aW5nIHdoZXJlIHRvIHBsYWNlIGFuIGFpcnBvcnQsIGFzIHlvdSB3YW50IGEgbG9jYXRpb24gdGhhdCBpcyBlYXN5IHRvIGFjY2VzcyB2aWEgcGxhbmUuDQogIA0KDQpgYGANCg0K