library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Dataset 1: Customers
customers <- tibble(
  customer_id = c(1, 2, 3, 4, 5),
  name = c("Alice", "Bob", "Charlie", "David", "Eve"),
  city = c("New York", "Los Angeles", "Chicago", "Houston", "Phoenix")
)

# Dataset 2: Orders
orders <- tibble(
  order_id = c(101, 102, 103, 104, 105, 106),
  customer_id = c(1, 2, 3, 2, 6, 7),
  product = c("Laptop", "Phone", "Tablet", "Desktop", "Camera", "Printer"),
  amount = c(1200, 800, 300, 1500, 600, 150)
)

Inner Join (3 points) Perform an inner join between the customers and orders datasets.

q1 <- inner_join(customers , orders )
## Joining with `by = join_by(customer_id)`

How many rows are in the result?

nrow(q1)
## [1] 4

Why are some customers or orders not included in the result?

Inner join returns all rows from both tables where there is a match, therefore the rows not returned did not have a match in the other table

Display the result

head(q1)
## # A tibble: 4 × 6
##   customer_id name    city        order_id product amount
##         <dbl> <chr>   <chr>          <dbl> <chr>    <dbl>
## 1           1 Alice   New York         101 Laptop    1200
## 2           2 Bob     Los Angeles      102 Phone      800
## 3           2 Bob     Los Angeles      104 Desktop   1500
## 4           3 Charlie Chicago          103 Tablet     300

Left Join (3 points) Perform a left join with customers as the left table and orders as the right table.

q2 <- left_join(customers, orders )
## Joining with `by = join_by(customer_id)`

How many rows are in the result?

nrow(q2)
## [1] 6

Explain why this number differs from the inner join result.

Left join returns all rows from the left table and matching rows from the right table, therefore all customers were joined, even those without orders.

Display the result

head(q2)
## # A tibble: 6 × 6
##   customer_id name    city        order_id product amount
##         <dbl> <chr>   <chr>          <dbl> <chr>    <dbl>
## 1           1 Alice   New York         101 Laptop    1200
## 2           2 Bob     Los Angeles      102 Phone      800
## 3           2 Bob     Los Angeles      104 Desktop   1500
## 4           3 Charlie Chicago          103 Tablet     300
## 5           4 David   Houston           NA <NA>        NA
## 6           5 Eve     Phoenix           NA <NA>        NA

Right Join (3 points) Perform a right join with customers as the left table and orders as the right table.

q3 <- right_join(customers, orders )
## Joining with `by = join_by(customer_id)`

How many rows are in the result?

nrow(q3)
## [1] 6

Which customer_ids in the result have NULL for customer name and city? Explain why.

Customer_id 6 and customer_id 7 have NULLs for name and city because these two rows exist in orders, but not in customers. This is because a right join keeps all orders, even if there is no matching customer.

Display the result

head(q3)
## # A tibble: 6 × 6
##   customer_id name    city        order_id product amount
##         <dbl> <chr>   <chr>          <dbl> <chr>    <dbl>
## 1           1 Alice   New York         101 Laptop    1200
## 2           2 Bob     Los Angeles      102 Phone      800
## 3           2 Bob     Los Angeles      104 Desktop   1500
## 4           3 Charlie Chicago          103 Tablet     300
## 5           6 <NA>    <NA>             105 Camera     600
## 6           7 <NA>    <NA>             106 Printer    150

Full Join (3 points) Perform a full join between customers and orders.

q4 <- full_join(customers, orders )
## Joining with `by = join_by(customer_id)`

How many rows are in the result?

nrow(q4)
## [1] 8

Identify any rows where there’s information from only one table. Explain these results.

For customer id 4 and customer id 5 there are no orders, therefore NA is listed in the columns for order info. Orders with customer_id 6 and customer_id 7 have no matching customers, therefore NA is listed for customer info.

Display the result

head(q4)
## # A tibble: 6 × 6
##   customer_id name    city        order_id product amount
##         <dbl> <chr>   <chr>          <dbl> <chr>    <dbl>
## 1           1 Alice   New York         101 Laptop    1200
## 2           2 Bob     Los Angeles      102 Phone      800
## 3           2 Bob     Los Angeles      104 Desktop   1500
## 4           3 Charlie Chicago          103 Tablet     300
## 5           4 David   Houston           NA <NA>        NA
## 6           5 Eve     Phoenix           NA <NA>        NA

Semi Join (3 points) Perform a semi join with customers as the left table and orders as the right table.

q5 <- semi_join(customers, orders )
## Joining with `by = join_by(customer_id)`

How many rows are in the result?

nrow(q5)
## [1] 3

How does this result differ from the inner join result?

Semi join returns the rows from the left table where there is a match in the right table, therefore, semi join only returns the columns from customers, but still filters by those with at least one matching order.

Display the result

head(q5)
## # A tibble: 3 × 3
##   customer_id name    city       
##         <dbl> <chr>   <chr>      
## 1           1 Alice   New York   
## 2           2 Bob     Los Angeles
## 3           3 Charlie Chicago

Anti Join (3 points) Perform an anti join with customers as the left table and orders as the right table.

q6 <- anti_join(customers, orders )
## Joining with `by = join_by(customer_id)`

Which customers are in the result?

David, customer_id 4, and Eve, customer_id 5, are displayed in the result.

Explain what this result tells you about these customers.

This result tells us that these two customers have not placed any orders, therefore, they do not appeaer in the orders table.

Display the result

head(q6)
## # A tibble: 2 × 3
##   customer_id name  city   
##         <dbl> <chr> <chr>  
## 1           4 David Houston
## 2           5 Eve   Phoenix

Practical Application (4 points) Imagine you’re analyzing customer behavior.

Which join would you use to find all customers, including those who haven’t placed any orders? Why?

You should use the left join to find all customers, because left join includes all customers even those who have not placed orders.

Which join would you use to find only the customers who have placed orders? Why?

You should use the inner join to find only the customers who have placed orders because that table will only return customers with matching customer_id in both tables.

Write the R code for both scenarios

## All customers (even without orders)
all_customers <- left_join(customers, orders )
## Joining with `by = join_by(customer_id)`
## Only customers who have placed orders
customers_with_orders <- inner_join(customers, orders)
## Joining with `by = join_by(customer_id)`

Display the result

head(all_customers)
## # A tibble: 6 × 6
##   customer_id name    city        order_id product amount
##         <dbl> <chr>   <chr>          <dbl> <chr>    <dbl>
## 1           1 Alice   New York         101 Laptop    1200
## 2           2 Bob     Los Angeles      102 Phone      800
## 3           2 Bob     Los Angeles      104 Desktop   1500
## 4           3 Charlie Chicago          103 Tablet     300
## 5           4 David   Houston           NA <NA>        NA
## 6           5 Eve     Phoenix           NA <NA>        NA
head(customers_with_orders)
## # A tibble: 4 × 6
##   customer_id name    city        order_id product amount
##         <dbl> <chr>   <chr>          <dbl> <chr>    <dbl>
## 1           1 Alice   New York         101 Laptop    1200
## 2           2 Bob     Los Angeles      102 Phone      800
## 3           2 Bob     Los Angeles      104 Desktop   1500
## 4           3 Charlie Chicago          103 Tablet     300

Challenge Question (3 points) Create a summary that shows each customer’s name, city, total number of orders, and total amount spent. Include all customers, even those without orders. Hint: You’ll need to use a combination of joins and group_by/summarize operations.

customer_summary <- customers %>%
  left_join(orders) %>%
  group_by(name, city) %>%
  summarize(
    total_orders = n_distinct(order_id, na.rm = TRUE),
    total_spent = sum(amount, na.rm = TRUE),
    .groups = "drop"
  )
## Joining with `by = join_by(customer_id)`
customer_summary
## # A tibble: 5 × 4
##   name    city        total_orders total_spent
##   <chr>   <chr>              <int>       <dbl>
## 1 Alice   New York               1        1200
## 2 Bob     Los Angeles            2        2300
## 3 Charlie Chicago                1         300
## 4 David   Houston                0           0
## 5 Eve     Phoenix                0           0