R
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Data Structures
-
Section 4: Data Manipulation
-
Section 5: Visualization and Statistics
-
Section 6: Advanced R
-
Section 7: Practical Projects
-
Section 8: Interview Practice
-
Section 9: More Practice Exercises
-
Section 10: Shiny Apps in Depth
-
Section 11: More Data Wrangling
-
Section 12: Tidyverse Deep Dive
-
Section 13: Statistical Modeling Deep Dive
-
Section 14: Machine Learning in R
-
Section 15: R Visualization Deep Dive
-
Section 16: R Package Development Deep Dive
-
Section 17: R for Reproducible Research
-
Section 18: R and Databases
-
Section 19: R Performance Optimization
-
Section 20: Bioinformatics and Specialized R
-
Section 21: More Shiny Practice
-
Section 22: More Practice Exercises
-
Section 23: R Data Structures Deep Dive
-
Section 24: More Interview and Review
-
Section 25: R for Business Analytics
-
Section 26: R Text Mining and NLP
-
Section 27: R Spatial Data Analysis
-
Section 28: R Deep Learning
-
Section 29: Advanced Statistical Techniques
-
Section 30: R Object Systems Deep Dive
-
Section 31: R Environments and Metaprogramming
-
Section 32: R for Finance
-
Section 33: R for Clinical and Health Data
-
Section 34: More Shiny Advanced Practice
-
Section 35: R Data Cleaning Deep Dive
-
Section 36: R Reporting Automation
-
Section 37: More Practical Projects Round 2
-
Section 38: R Ecosystem and Career
-
Section 39: More Visualization Practice
-
Section 40: R for Experimentation
-
Section 41: R for Genomics and Bioinformatics Deep Dive
-
Section 42: R for Marketing Analytics
-
Section 43: R Data Import/Export Deep Dive
-
Section 44: R String Processing Deep Dive
-
Section 45: R for Actuarial and Insurance Analytics
-
Section 46: R Testing and Quality Assurance Deep Dive
-
Section 47: R Version Control and Collaboration
-
Section 48: R Advanced Functional Programming
-
Section 49: R for Supply Chain and Operations
-
Section 50: More Practice Exercises Round 3
-
Section 51: R Dashboards and BI Integration
-
Section 52: R Data Governance and Ethics
-
Section 53: More Modeling Practice
-
Section 54: R Final Capstone Projects
-
Section 55: R for Sports Analytics
-
Section 56: More Interview Practice Round 2
-
Section 57: R Networking and APIs
-
Section 58: R for Environmental Science
-
Section 59: R Notebook and Documentation Practices
-
Section 60: More Data Wrangling Mastery
-
Section 61: R for A/B Testing at Scale
-
Section 62: R Package Ecosystem Deep Dive
48: Date and Time Handling with lubridate
If you've spent any time with base R, you know that dealing with dates and times can feel like a fight you're destined to lose. The formats are finicky, and the `POSIXct` and `POSIXlt` classes are, frankly, a headache. That's why we use lubridate. It turns date-time manipulation into something that actually feels intuitive.
To show you how this works, let's imagine we're analyzing a small set of logs from a temperature sensor. We have a few timestamps and the recorded temperature, but they're currently just strings in a data frame. We need to find out how much time elapsed between readings and what time of day the sensor is most active.
Cleaning up messy sensor timestamps
First, let's set up our data. I've got a few readings here. Notice that they are in a "Year-Month-Day Hour:Minute:Second" format.
library(lubridate)
sensor_data <- data.frame(
timestamp = c("2023-10-01 08:30:00", "2023-10-01 08:45:12",
"2023-10-01 09:15:00", "2023-10-02 02:00:00"),
temp = c(22.1, 22.5, 23.0, 18.4),
stringsAsFactors = FALSE
)
The magic of lubridate is that it provides functions that match the order of the elements in your string. Since my data is Year, then Month, then Day, followed by hours, minutes, and seconds, I'll use ymd_hms().
sensor_data$timestamp <- ymd_hms(sensor_data$timestamp)
Fixing my parsing blunder
Wait, I actually messed up. When I first wrote this script, I tried to use ymd() because I only cared about the date. But when I ran it, R stripped out all the time information, leaving me with just 2023-10-01. I lost the precision I needed for the interval calculations.
If you ever see your time data suddenly "truncate" after a conversion, check your function. ymd() is for dates; ymd_hms() is for date-times. I've corrected it above, and now sensor_data$timestamp is a proper POSIXct object that preserves the exact second the sensor fired.
Measuring the gaps between pings
Now I want to know the time elapsed between each reading. In base R, subtracting dates gives you a difftime object, which can be annoying to work with if you want a specific unit (like seconds or minutes).
I'll use interval() to create a span of time between the first and second readings, and then wrap that in as.duration() to make it easy to convert to a numeric value.
# Let's find the gap between the first two readings
start_time <- sensor_data$timestamp[1]
end_time <- sensor_data$timestamp[2]
gap <- interval(start_time, end_time)
duration_minutes <- as.duration(gap) / 60
print(duration_minutes)
# Result: 15.2 minutes
I prefer interval because it represents a specific period of time on the calendar, whereas duration is just a length of time. It's a subtle distinction, but it matters when you start dealing with daylight savings time shifts.
Finding the peak activity hour
Finally, let's say we want to group these readings by the hour of the day to see when the sensor is most active. lubridate makes this trivial with "component" functions. Instead of complex formatting strings, you just use hour().
sensor_data$hour_of_day <- hour(sensor_data$timestamp)
# Now we can easily see the hours
print(sensor_data[, c("timestamp", "hour_of_day")])
By extracting the hour into its own column, we can now use standard aggregation tools (like table() or dplyr) to find the peak windows. It's much cleaner than trying to parse the string manually or using strftime().
📋 Practical Task
Calculating Flight Durations for a Regional Airline
You have been given a small dataset of flight departures and arrivals. Your task is to calculate the total travel time for each flight in minutes.
flights <- data.frame(
flight_id = c("AA101", "DL202", "UA303"),
departure = c("2023-11-15 10:00:00", "2023-11-15 13:30:00", "2023-11-16 08:15:00"),
arrival = c("2023-11-15 12:45:00", "2023-11-15 16:00:00", "2023-11-16 11:30:00"),
stringsAsFactors = FALSE
)
Requirements:
- Convert the
departureandarrivalcolumns into proper date-time objects usinglubridate. - Create a new column called
duration_minthat stores the difference between arrival and departure in minutes. - Extract the day of the week for each departure and store it in a column called
departure_day(Hint: usewday()). - Print the final data frame.
There are no comments for now.