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
78: dbplyr for Remote Data Sources
I've run into this a lot in production: you're working with a dataset that's just too big for your laptop's RAM. Maybe it's a few hundred million rows of clickstream data or a massive retail ledger. Your first instinct is usually to pull the whole table into R and then filter it down, but that's a great way to freeze your entire system.
Let's look at how we handle this using dbplyr. I'm going to set up a quick SQLite database with a hypothetical store_sales table so we can walk through the logic together.
library(dplyr)
library(dbplyr)
library(RSQLite)
The RAM Wall
Usually, we're tempted to do something like dbReadTable(con, "store_sales"). I tried that on a project a few years back with a 50GB table, and R just gave up. The problem is that dbReadTable pulls the entire dataset into your local memory. We want the database to do the heavy lifting, not R.
Instead, let's try creating a reference to the table without actually loading the data:
# Connect to a dummy database
con <- dbConnect(RSQLite::SQLite(), ":memory:")
# (Assuming we've already populated 'store_sales' in the DB)
sales_remote <- tbl(con, "store_sales")
Now, if you print sales_remote to the console, you'll see something interesting. It looks like a tibble, but if you look closely at the header, it says # Source: dbplyr lazy table. This is the "magic" part. I haven't actually downloaded a single row of data yet. I've just told R, "Hey, there is a table over there called store_sales, and I want you to keep track of it."
Testing the Lazy Pipeline
Since it's a "lazy" table, I can start writing dplyr code as if the data were already in R. Let's say I only want the total revenue for the 'Electronics' department where the sale was over $100.
revenue_query <- sales_remote
%> filter(department == "Electronics", amount > 100)
%> summarise(total = sum(amount, na.rm = TRUE))
I'll run that, and... nothing happened. Well, not "nothing," but R didn't actually calculate the sum. It just updated the revenue_query object. If I print revenue_query now, it still says it's a lazy table. This is where a lot of people get confused; they think their code isn't working because they don't see the final number.
Peeking Under the Hood
I always do this when I'm debugging a dbplyr pipeline. I want to know exactly what SQL R is sending to the server. If the SQL is inefficient, the query will be slow, regardless of how clean my R code looks.
show_query(revenue_query)
When I run this, R spits out the actual SQL: SELECT sum("amount") AS "total" FROM "store_sales" WHERE ("department" = 'Electronics' AND "amount" > 100). That's the beauty of it. R isn't doing the math; it's translating my tidyverse verbs into a language the database understands. The database filters the millions of rows and only prepares the one single number I actually asked for.
The Moment of Truth: collect()
So, we have a query that is ready to go, but it's still "remote." To actually bring that result into my R session as a standard data frame, I need to use collect().
final_result <- revenue_query %> collect()
Now final_result is a regular R tibble. The crucial part here is that I called collect() at the very end of the chain. If I had called collect() right after sales_remote, I would have pulled the entire million-row table into memory, defeating the whole purpose of using dbplyr. Always filter and summarise as much as possible on the remote side before bringing the data home.
📋 Practical Task
Exercise: Optimizing the Regional Performance Report
You have been given access to a remote PostgreSQL database containing a table called web_logs. This table is massive (terabytes of data) and contains columns user_id, region, page_views, and session_duration.
Your goal is to calculate the average session_duration for users in the 'North America' region who had more than 5 page_views. You must do this without crashing the R session.
Requirements:
- Use
tbl()to create a remote reference toweb_logs. - Use
filter()to isolate 'North America' andpage_views > 5. - Use
summarise()to find the mean ofsession_duration. - Use
show_query()to verify that the filtering is happening in SQL, not in R. - Use
collect()as the final step to bring the single resulting average into your R environment.
Starter Code:
# Assume 'con' is already established
logs_remote <- tbl(con, "web_logs")
# Your code here...
There are no comments for now.