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
14: Tibbles vs Base Data Frames
I've seen this exact bug trip up plenty of developers transitioning from base R to the Tidyverse. You're working with what looks like a standard data frame, you try to pull a single column to run a calculation, and suddenly R is throwing a cryptic error telling you that your numeric data isn't actually numeric.
library(tibble)
# Creating a small dataset of server response times
logs <- tibble(
endpoint = c("/home", "/api/v1/user", "/login", "/settings"),
latency = c(120, 450, 80, 210)
)
# I want the average latency, so I'll grab the second column
avg_latency <- mean(logs[, 2])
# Error in mean.default(logs[, 2]) :
# argument is not numeric or logical: returning NA
The "Vector vs. Tibble" Indexing Trap
If logs were a base R data.frame, that code would work perfectly. In base R, when you use a single bracket [, 2] to select one column, R "simplifies" the result. It says, "Oh, you only want one column? I'll just give you a plain old vector."
Tibbles are different. They are designed to be consistent. A tibble is a data frame, and they believe that slicing a data frame should always return another data frame (or tibble). So, logs[, 2] isn't returning a numeric vector of latencies; it's returning a 4x1 tibble that contains a numeric vector. The mean() function has no idea what to do with a tibble object, so it fails.
Forcing a Vector Return with Double Brackets
To fix this, you need to be explicit about wanting the underlying data, not a miniature table. The cleanest way to do this is using double brackets [[ ]]. While single brackets slice the table, double brackets "reach inside" and grab the actual element.
# This reaches inside the tibble and pulls out the actual numeric vector
avg_latency <- mean(logs[[2]])
# Result: 215
# Or, even better, use the column name for readability
avg_latency <- mean(logs[["latency"]])
# Result: 215
I generally recommend using the $ operator (e.g., logs$latency) for quick interactive work, but [[ ]] is more robust when you're writing functions where the column index or name might be stored in a variable.
Why we put up with this (The Tibble Advantage)
You might be wondering why we'd want a "stricter" data frame that breaks base R indexing. In my experience, the trade-off is worth it for two main reasons: printing and type safety.
- Sane Printing: If you accidentally print a base data frame with 100,000 rows, R will try to dump every single one of them into your console, likely freezing your IDE. A tibble only prints the first 10 rows and tells you how many more are hidden. It's a lifesaver.
- No More Secret Conversions: In older versions of base R,
data.frame()would automatically convert strings to factors. This caused endless headaches. Tibbles never change the type of your input data. What you put in is exactly what you get out.
📋 Practical Task
Debugging the Monthly Revenue Summary
You have been handed a script that calculates the total revenue from a tibble of sales. However, the original author used base R indexing logic, and the script is currently returning NA instead of a sum.
Your Task: Fix the total_rev calculation so that it correctly extracts the amount column as a vector and sums it up.
library(tibble)
sales_data <- tibble(
transaction_id = c(101, 102, 103, 104),
customer = c("Alice", "Bob", "Charlie", "Diana"),
amount = c(150.00, 200.50, 50.25, 300.00)
)
# FIX THIS LINE:
total_rev <- sum(sales_data[, 3])
print(total_rev)
There are no comments for now.