LEGO

Packages

We’ll use the tidyverse package for much of the data wrangling and visualization. The tidyverse package should be installed by now on your computer. If not, take again a look at the Set Up tutorial. You can load the tidyverse with the following command:

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Data

The data is contained in the file lego.csv and can be found on Moodle in the folder Data files, Quarto files and Solutions to previous problem sets.

It is simulated data based on real prices for LEGO sales in 2018 in the United States. Names and hobbies have been randomly generated. The dataset contains the following variables.

Variable Description
first_name First name of customer
last_name Last name of customer
age Age of customer
phone_number Phone number of customer
set_id Set ID of LEGO set purchased
number Item number of LEGO set purchased
theme Theme of LEGO set purchased
subtheme Sub theme of LEGO set purchased
year Year of purchase
name Name of LEGO set purchased
pieces Number of pieces of LEGOs in set purchased
us_price Price of the set purchased in US Dollars
quantity Quantity of LEGO set(s) purchased

Solutions

Solution 1. Save the data and the starter file appropriately so the following code works.

lego <- read_csv("data/lego.csv")
Rows: 620 Columns: 13
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (7): first_name, last_name, phone_number, number, theme, subtheme, name
dbl (6): age, set_id, year, pieces, us_price, quantity

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Remark: Don’t forget to remove eval: false or change it to eval: true.

Take a glimpse at the data.

lego
# A tibble: 620 × 13
   first_name last_name      age phone_number set_id number theme subtheme  year
   <chr>      <chr>        <dbl> <chr>         <dbl> <chr>  <chr> <chr>    <dbl>
 1 Kimberly   Beckstead       24 216-555-2549  24701 76062  DC C… Mighty …  2018
 2 Neel       Garvin          35 819-555-3189  25626 70595  Ninj… Rise of…  2018
 3 Neel       Garvin          35 819-555-3189  24665 21031  Arch… <NA>      2018
 4 Chelsea    Bouchard        41 <NA>          24695 31048  Crea… <NA>      2018
 5 Chelsea    Bouchard        41 <NA>          25626 70595  Ninj… Rise of…  2018
 6 Chelsea    Bouchard        41 <NA>          24721 10831  Duplo <NA>      2018
 7 Bryanna    Welsh           19 <NA>          24797 75138  Star… Episode…  2018
 8 Bryanna    Welsh           19 <NA>          24701 76062  DC C… Mighty …  2018
 9 Caleb      Garcia-Wide…    37 907-555-9236  24730 41115  Frie… <NA>      2018
10 Caleb      Garcia-Wide…    37 907-555-9236  25611 21127  Mine… Minifig…  2018
# ℹ 610 more rows
# ℹ 4 more variables: name <chr>, pieces <dbl>, us_price <dbl>, quantity <dbl>

Solution 2. The three most common names (number) are Jackson (13), Jacob (11), and Joseph (11)

lego |> 
  count(first_name) |>
  arrange(desc(n))
# A tibble: 211 × 2
   first_name     n
   <chr>      <int>
 1 Jackson       13
 2 Jacob         11
 3 Joseph        11
 4 Michael       10
 5 Audrey         8
 6 Connor         8
 7 Kaitlyn        8
 8 Lucas          8
 9 Amanda         7
10 Joshua         7
# ℹ 201 more rows

Solution 3. Remove this text, and add your answer for Exercise 3 here. Complete the given R code. Remove the chunk option eval: false.

lego <- lego |> 
  drop_na(subtheme)

lego
# A tibble: 448 × 13
   first_name last_name      age phone_number set_id number theme subtheme  year
   <chr>      <chr>        <dbl> <chr>         <dbl> <chr>  <chr> <chr>    <dbl>
 1 Kimberly   Beckstead       24 216-555-2549  24701 76062  DC C… Mighty …  2018
 2 Neel       Garvin          35 819-555-3189  25626 70595  Ninj… Rise of…  2018
 3 Chelsea    Bouchard        41 <NA>          25626 70595  Ninj… Rise of…  2018
 4 Bryanna    Welsh           19 <NA>          24797 75138  Star… Episode…  2018
 5 Bryanna    Welsh           19 <NA>          24701 76062  DC C… Mighty …  2018
 6 Caleb      Garcia-Wide…    37 907-555-9236  25611 21127  Mine… Minifig…  2018
 7 Kevin      Cruz            20 947-555-7946  24767 70335  Nexo… Ultimate  2018
 8 Connor     Brown           36 516-555-4310  24548 71230  Dime… Fun Pack  2018
 9 Connor     Brown           36 516-555-4310  24913 60112  City  Fire      2018
10 Connor     Brown           36 516-555-4310  26034 41573  Mixe… Series 9  2018
# ℹ 438 more rows
# ℹ 4 more variables: name <chr>, pieces <dbl>, us_price <dbl>, quantity <dbl>

REMARK: Use the reduced dataset to answer the following questions.

Solution 4. The three most common themes are Star Wars (n = 75), Gear (n = 55), and Mixels (n = 55). Among these, the most common subsets are The Force Awakens (n = 17), Role-Play toys (n = 7) for Gear, and Series 9 (n = 21) for Mixels.

popular_themes <- lego |>
  group_by(theme) |>
  count(theme, sort = TRUE) |>
  head(3)

popular_themes
# A tibble: 3 × 2
# Groups:   theme [3]
  theme         n
  <chr>     <int>
1 Star Wars    75
2 Gear         55
3 Mixels       55

You can solve the task in two steps

popular_themes <- lego |>
  filter(theme %in% popular_themes$theme) |>
  group_by(theme) |>
  count(subtheme, sort = TRUE) |>
  slice(1)

popular_themes
# A tibble: 3 × 3
# Groups:   theme [3]
  theme     subtheme              n
  <chr>     <chr>             <int>
1 Gear      Role-Play toys        7
2 Mixels    Series 9             21
3 Star Wars The Force Awakens    15

Solution 5. Check.

lego <- lego |> 
  mutate(age_group = case_when(
  age <= 18 ~ "18 and under",
  age > 18 & age <= 25 ~ "19 - 25",
  age > 25 & age <= 35 ~ "26 - 35",
  age > 35 & age <= 50 ~ "36 - 50",
  age >= 51 ~ "51 and over"
    ) 
  )

Solution 6. Remove this text, and add your answer for Exercise 6 here. Complete the given R code. Remove the chunk option eval: false.

lego |> 
  group_by(age_group) |>
  mutate(set_quantity = sum(quantity)) |>
  count(set_quantity, sort = TRUE) |>
  select(-n)
# A tibble: 5 × 2
# Groups:   age_group [5]
  age_group    set_quantity
  <chr>               <dbl>
1 36 - 50               232
2 26 - 35               193
3 19 - 25               119
4 51 and over            73
5 18 and under           33

Solution 7.

lego |> 
  filter(theme %in% c("City", "Nexo Knights", "Ninjago")) |>
  ggplot(aes(x = theme, fill = age_group)) +
    geom_bar() +
    scale_fill_brewer(palette = "Set1") +
    labs(
      title = "Distribution of age within each of the three popular themes",
      x = "Popular Lego Theme", 
      y = "count",
      fill = "Age Group"
    )

Between the variables theme and age_group, while only weak, there is some association present. It appears, for example, that almost twice as many costumers above the age of 52 purchase Ninjago sets than City sets, although more total City sets are purchased. This stands out as a rather unique case though, as the distribution appears quite constant in each relative theme given the total sets of each theme purchased.there is some association between the variables (the themes City, Nexo Kings, and Ninjago) present. It appears, for example, that almost twice as many costumers above the age of 52 purchase Ninjago sets than City sets, although more total City sets are purchased. This appears to be a rather unique case though, as the distribution appears quite constant in each relative theme given the total sets of each theme purchased.

Solution 8. Costumers in the age group 36 - 50 spend the most on LEGOs ($7063.68)

lego |> 
  group_by(age_group) |>
  mutate(total_spending = sum(quantity * us_price)) |>
  count(total_spending, sort = TRUE) |>
  select(-n)
# A tibble: 5 × 2
# Groups:   age_group [5]
  age_group    total_spending
  <chr>                 <dbl>
1 36 - 50               7064.
2 26 - 35               4872.
3 19 - 25               3377.
4 51 and over           1877.
5 18 and under           809.

Solution 9. 158 observation are from the age_group 36 - 50. 35 bought a set from the Star Wars or from the Ninjago theme.

#how many observation are from the age group 36 - 50?
lego |> 
  filter(age_group == "36 - 50") |>
  count()
# A tibble: 1 × 1
      n
  <int>
1   158
#how many observations from this group are from either of the themes Star Wars or Ninjago?
lego |> 
  filter(age_group == "36 - 50" & theme == "Star Wars" | age_group == "36 - 50" & theme == "Ninjago") |>
  count()
# A tibble: 1 × 1
      n
  <int>
1    35