The purpose of Project 2 is to practice and refine skills in transforming wide-format datasets into tidy long formats suitable for analysis. For my first dataset, I selected the Air Quality dataset from the UCI Machine Learning Repository. The dataset can be accessed directly from the UCI Machine Learning Repository and the data can be extracted using the ucimlrepo R package. I was able to do this by following the technical setup outlined on the ucimlrepo R Package Site. For my other two datasets, I selected wide-format data posted by my classmates in Discussion 5A: a child sleep schedule posted by Noelle Messaoudi and annual health center visit metrics posted by Renee Watson.
Loading the Data
I’m choosing to load all the data in one step, then calling each dataset at the beginning of each section to work on each separately.
Code
# Fetch the dataset from the UCI data repositoryuci_data <-fetch_ucirepo(name ="Air Quality")# Extract the original datasetair_data <- uci_data$data$original# url for sleep schedule dataseturl1 <-"https://raw.githubusercontent.com/Dave-Melchor/Data-607-Data-Acquisition-and-Management/refs/heads/main/data/raw/sleep_schedule.csv"# url for health center visits dataseturl2 <-"https://raw.githubusercontent.com/Dave-Melchor/Data-607-Data-Acquisition-and-Management/refs/heads/main/data/raw/annual_health_center_visits.csv"# Import sleep schedule datasetschedule <-import(url1)# Import health center visits datasetvisits <-import(url2)
DATA TIDYING
Once the data has been imported, we are asked to demonstrate the following transformations explicitly:
Reshape from wide to tidy (long) format
Normalize variable structure
Rename variables to follow a consistent naming convention
Address missing or inconsistent values with documented handling decisions
I will work with one data set at a time, completing all steps from start to finish and repeating the process for each data set until all three have gone through the transformation process.
# rename variables according to data dictionaryair_data <- air_data |>rename(date = Date,time = Time,co_true =`CO(GT)`,sensor_tin_oxide =`PT08.S1(CO)`,nmhc_true =`NMHC(GT)`,benzene_true =`C6H6(GT)`,sensor_titania =`PT08.S2(NMHC)`,nox_true =`NOx(GT)`,sensor_tungsten_nox =`PT08.S3(NOx)`,no2_true =`NO2(GT)`,sensor_tungsten_no2 =`PT08.S4(NO2)`,sensor_indium_oxide =`PT08.S5(O3)`,temperature_c = T,relative_humidity = RH,absolute_humidity = AH )# missing values are tagged with -200, change -200 to NAair_data <- air_data |>mutate(across(where(is.numeric), ~na_if(.x, -200)))# let's pivot this data to a long formatair_data <- air_data |>pivot_longer(cols =-c(date, time),names_to ="measurement_type",values_to ="values" )
ANALYSIS
Now that the data has been transformed, we are asked to include the following outputs as appropriate for each analysis:
Summary tables with clearly labeled columns and units
Visualizations with axis labels, titles, and legends
A brief narrative interpreting each result in context
For the air quality data, I want to know how temperature affects different air pollutants.
Code
# isolate temperature with date and timetemp_data <- air_data |>filter(measurement_type =="temperature_c") |>select(date, time, temperature_c = values)# isolate pollutantspollutants <- air_data |>filter(measurement_type %in%c("co_true", "benzene_true", "nox_true", "no2_true", "nmhc_true")) |>rename(pollutant_type ="measurement_type" )# join temperature and pollutants togetherpollutant_temp_analysis <- pollutants |>inner_join(temp_data, by =c("date", "time"))
Code
p_pollutant_tempt <- pollutant_temp_analysis |>ggplot(aes(x = temperature_c,y = values,color = pollutant_type)) +geom_point(alpha =0.2) +geom_smooth(method ="lm",colour ="black",se =FALSE) +facet_wrap(~ pollutant_type,scales ="free_y") +labs(title ="Air Quality Analysis Based on Outside Temperature",subtitle ="Pollutant behavior according to temperature changes",x ="Temperature (°C)",y ="Concentration Value",color ="Pollutant",caption ="Source: UCI Air Quality Dataset") +theme_minimal() +theme(plot.title =element_text(face ="bold") )# show graphp_pollutant_tempt
Discussion
An analysis of pollutant concentrations relative to ambient temperature reveals distinct patterns across chemical species:
Non-Methane Hydrocarbons (NMHC): Exhibited a steep positive relationship with temperature, indicating that concentrations rise sharply as ambient temperatures increase. However, measurements for NMHC are constrained to a truncated temperature range between roughly 10°C and 30°C, after which data points are absent.
Benzene & Carbon Monoxide (CO): Benzene displays a slight positive trend as temperature increases. Carbon monoxide (co_true), on the other hand, shows an almost entirely flat regression line, suggesting its ambient concentrations remain largely independent of temperature variations.
Nitrogen Dioxide (NO2) & Nitrogen Oxides (NOx): Both nitrogen species display negative sloped trendlines, demonstrating that concentrations for NO2 and NOx tend to decrease as ambient temperature rises.
Baby Schedule
Next, I am going to follow the same format as I did for the air quality dataset and work with the baby schedule data provided by my classmate.
Code
str(schedule)
'data.frame': 2 obs. of 7 variables:
$ \f0\fs24 \cf0 Week: int 1 2
$ Monday Nap (min) : int 90 75
$ Mon Bedtime : chr "8:00 PM" "8:15 PM"
$ Tuesday Nap (min) : int 60 120
$ Tuesday bedtime : chr "8:00 PM" "8:30 PM"
$ Wednesday nap (min) : int 0 45
$ Wednesday Bedtime\ : chr "7:30 PM\\" "8:00 PM}"
This dataset provides data for how many minutes the baby napped and what time the baby went to sleep for the night The days provided are Monday, Tuesday and Wednesday for a period of two consecutive weeks.
# Standardize day labels for ordered plottingschedule_tidy <- schedule_tidy |>mutate(day_of_week =factor(stringr::str_to_title(day_of_week), levels =c("Monday", "Tuesday", "Wednesday")))p_schedule_tidy <- schedule_tidy |>ggplot(aes(x = day_of_week, y = nap_time, fill =as.factor(week))) +geom_col(position ="dodge") +labs(title ="Baby Nap Duration Across Weekdays",subtitle ="Comparing nap lengths (minutes) between Week 1 and Week 2",x ="Day of Week",y ="Nap Duration (minutes)",fill ="Week",caption ="Source: Baby Sleep Schedule Dataset" ) +theme_minimal() +theme(plot.title =element_text(face ="bold"))# display plotp_schedule_tidy
Code
# summarise datasleep_summary <- schedule_tidy |>group_by(day_of_week) |>summarise(avg_nap_min =mean(nap_time, na.rm =TRUE),total_nap_min =sum(nap_time, na.rm =TRUE) )# create a sleep summary table t_sleep_summary <- sleep_summary |>kable(col.names =c("Day of Week", "Average Nap (min)", "Total Nap (min)"),align =c("l", "c", "c"),caption ="Table 1: Summary of Baby Nap Duration by Day of Week" )# display table t_sleep_summary
Table 1: Summary of Baby Nap Duration by Day of Week
Day of Week
Average Nap (min)
Total Nap (min)
Monday
82.5
165
Tuesday
90.0
180
Wednesday
22.5
45
Discussion
When looking at the baby’s sleep pattern by day, the plot of nap durations across weekdays reveals that Wednesdays are the days when the baby’s naps are shortest. During the first week, we can also see that when the baby didn’t take a nap, the bedtime schedule was the earliest of all days in this dataset.
Working with this dataset was enlightening because I got to practice on some unique commands like str_remove_all() and a more complex pivot_longer() function. I was able to figure out the pivot_longer() function by accessing Chapter 5: Data Tidying from the r4ds book found on this website. Also I was able to find help on regular expressions and string manipulation from the same book Chapter 15: Regular Expressions and Chapter 14: Strings.
Visits Data
Finally, we’ll be working with Renee’s annual health center’s visits data. We begin by exploring the data
Code
str(visits)
'data.frame': 10 obs. of 13 variables:
$ Clinic: chr "Harbor Community Health Center" "Riverside Family Health Clinic" "Central Community Health Center" "Eastside Family Clinic" ...
$ Jan : int 245 190 310 155 270 225 180 290 205 165
$ Feb : int 231 205 298 162 265 218 175 282 212 170
$ Mar : int 260 198 325 170 280 240 192 300 220 182
$ Apr : int 278 220 340 168 295 251 205 315 230 190
$ May : int 290 235 355 180 310 260 215 325 242 198
$ Jun : int 301 241 348 195 320 272 220 340 250 205
$ Jul : int 315 250 370 201 318 280 230 350 245 215
$ Aug : int 309 263 365 210 330 275 238 345 260 220
$ Sep : int 287 255 380 205 342 290 242 360 268 228
$ Oct : int 295 270 392 218 350 298 250 372 275 235
$ Nov : int 310 268 401 225 360 305 255 380 285 240
$ Dec : int 325 280 415 230 375 315 265 395 292 250
After loading and examining the visits data for the next part of the assignment, I noticed some formatting nuances in the dataset that made me question its integrity. I asked Google Gemini to help me understand what was going on, and it explained that although I saved my .txt file as a .csv file after creating it, it was saved in Rich Text format. As a result, it added the strange formatting tags like the on in the week column that looks like this, “\fs24 Week”. I also noticed that it was adding extra symbols to the observations, such as: “Wednesday Bedtime : chr”7:30 PM\” “8:00 PM}” “. I went back to where I saved the data and changed Renee’s dataframe to Plain Text format and that downloaded the data correctly, without the extra character. Since I already did all the work to fix the dataframe from Noelle, I’m choosing to leave the dataframe in Rich Text Format as a reminder to me that I should make sure I save my data in Plain Text format. Now that I figured that out, I will proceed to work with Renee’s health center dataframe that’s been saved in Plain Text format.
Now that the data is in a tidy format, we can use the data frame to construct plots that reveal overall patterns across health centers and months.
Code
# ggplot(visits_tidy, aes(x =reorder(Clinic, Counts, FUN = median), y = Counts, fill = Clinic)) +geom_boxplot(show.legend =FALSE, alpha =0.7) +geom_jitter(width =0.15, alpha =0.4, color ="black") +# shows raw monthly data pointscoord_flip() +labs(title ="Distribution of Monthly Health Center Visits by Clinic",subtitle ="Variation in monthly patient volume across 10 health centers",x ="Health Center Clinic",y ="Monthly Visit Count",caption ="Source: Discussion 5A Dataset (Renee Watson)" ) +theme_minimal() +theme(plot.title =element_text(face ="bold"),legend.position ="none")
Code
# order months chronologically rather than alphabeticallyvisits_tidy <- visits_tidy |>mutate(Month =factor(Month, levels =c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")))# plot of overall monthly visitsggplot(visits_tidy, aes(x = Month, y = Counts)) +geom_boxplot(fill ="steelblue", alpha =0.6) +labs(title ="Monthly Health Center Visit Totals Across All Clinics",subtitle ="Seasonal volume distribution throughout the year",x ="Month",y ="Visit Count",caption ="Source: Discussion 5A Dataset (Renee Watson)" ) +theme_minimal() +theme(plot.title =element_text(face ="bold"))
Table 2: Annual and Monthly Visit Volume Summary by Clinic
Health Center Clinic
Total Annual Visits
Mean Monthly Visits
Central Community Health Center
4299
358.2
Lakeside Community Clinic
4054
337.8
Westview Community Health Center
3815
317.9
Harbor Community Health Center
3446
287.2
Northside Health Clinic
3229
269.1
Parkview Health Center
2984
248.7
Riverside Family Health Clinic
2875
239.6
Greenwood Family Health Center
2667
222.2
Hillcrest Community Clinic
2498
208.2
Eastside Family Clinic
2319
193.2
Discussion
An analysis of the annual health center visit metrics shows patient volume across both facility locations and monthly trends:
Clinic Volume Differences: Total patient volume varies significantly by facility. Central Community Health Center consistently recorded the highest monthly visit counts, whereas Eastside Family Clinic maintained the lowest overall patient volume throughout the year.
Seasonal Progression: Patient visits show a steady rising trend across the calendar year. Across all clinics, visit counts start at their lowest in January and February and then increase each month, peaking in November and December.