Wrangling

Data wrangling with tidyverse
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.1     ✔ 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
library(naniar)
library(gtExtras)
## Loading required package: gt
## Warning: package 'gt' was built under R version 4.3.3
library(janitor)
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(ggplot2)  # for diamonds dataset
library(dplyr)    # for select function
data("diamonds") 
view(diamonds)

Filter subset by row

diamonds_sm <- filter(diamonds,cut == 'Ideal')

view(diamonds_sm)

diamonds_sm <- filter(diamonds, price > 10000)
view(diamonds_sm)
diamonds_sm <- filter(diamonds,
                      cut == 'Ideal',
                      price > 10000)

view(diamonds_sm)
miss_var_summary(diamonds_sm) %>%
  gt () %>% 
  gt_theme_guardian() %>% 
  
  tab_header(title = 'MISSING VALUE')
MISSING VALUE
variable n_miss pct_miss
carat 0 0
cut 0 0
color 0 0
clarity 0 0
depth 0 0
table 0 0
price 0 0
x 0 0
y 0 0
z 0 0
sum(is.na(diamonds_sm))
## [1] 0
# Count NA for column 
colSums(is.na(diamonds_sm))
##   carat     cut   color clarity   depth   table   price       x       y       z 
##       0       0       0       0       0       0       0       0       0       0
rowSums(is.na(diamonds_sm))
##    [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##   [38] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##   [75] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [149] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [186] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [223] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [260] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [297] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [334] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [371] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [408] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [445] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [482] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [519] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [556] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [593] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [630] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [667] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [704] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [741] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [778] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [815] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [852] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [889] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [926] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  [963] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1000] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1037] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1074] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1111] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1148] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1185] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1222] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1259] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1296] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1333] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1370] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1407] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1444] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1481] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1518] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1555] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1592] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1629] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1666] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1703] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [1740] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sum(is.na(diamonds))
## [1] 0

Sub set by column with select

diamonds_sm <- diamonds



diamonds_sm <- select(diamonds_sm,cut , color )

view(diamonds_sm)

diamonds_sm <- select(diamonds, 1:4)

view(diamonds_sm)

select() is used to choose columns,starts_with(‘c’) filters column names starting with the letter ‘c’

diamonds_sm <- select(diamonds, starts_with('c'))
view(diamonds_sm)

Also

diamonds_sm <- select(diamonds, contains('c'))
view(diamonds_sm)

order column with first diamonds,price and then the command everything equal all the rest

diamonds_sm <- select(diamonds, price , everything())

view(diamonds_sm)

Delay column

diamonds_sm <- select(diamonds, - price)

view(diamonds_sm)

same using pipe

diamonds_sm <- diamonds %>% 
  select(-price)
view(diamonds_sm)

reorder row with arrange by color will do asending standard

diamonds_sm <- diamonds %>% 
  arrange(color )
view(diamonds_sm)
diamonds_sm <- diamonds %>% 
  arrange(carat )
view(diamonds_sm)
diamonds_sm <- diamonds %>% 
  arrange(color,
          carat )
view(diamonds_sm)

arrange in desending order

diamonds_sm <- diamonds %>% 
  arrange(desc(carat ) )
view(diamonds_sm)

mutate modify and add column enrich data .20?: The .20 (or 0.20) represents 20%. This implies converting the carat weight (which is typically used for diamonds) into another unit or scale — in this case, grams.

diamonds_new <- diamonds %>% 
  mutate(mass_g = .20 * carat)
glimpse(diamonds_new)
## Rows: 53,940
## Columns: 11
## $ carat   <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, 0.23, 0.…
## $ cut     <ord> Ideal, Premium, Good, Premium, Good, Very Good, Very Good, Ver…
## $ color   <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, J, J, I,…
## $ clarity <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI1, VS1, …
## $ depth   <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, 59.4, 64…
## $ table   <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54, 62, 58…
## $ price   <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339, 340, 34…
## $ x       <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, 4.00, 4.…
## $ y       <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, 4.05, 4.…
## $ z       <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, 2.39, 2.…
## $ mass_g  <dbl> 0.046, 0.042, 0.046, 0.058, 0.062, 0.048, 0.048, 0.052, 0.044,…

add a colum of price per carat

diamonds_new <- diamonds %>% 
  mutate(mass_g = .20 * carat,
         price_per_carat = price / carat)

glimpse(diamonds_new)
## Rows: 53,940
## Columns: 12
## $ carat           <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, …
## $ cut             <ord> Ideal, Premium, Good, Premium, Good, Very Good, Very G…
## $ color           <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, …
## $ clarity         <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI…
## $ depth           <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, …
## $ table           <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54…
## $ price           <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339,…
## $ x               <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, …
## $ y               <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, …
## $ z               <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, …
## $ mass_g          <dbl> 0.046, 0.042, 0.046, 0.058, 0.062, 0.048, 0.048, 0.052…
## $ price_per_carat <dbl> 1417.391, 1552.381, 1421.739, 1151.724, 1080.645, 1400…
ggplot(diamonds_new, aes(x = mass_g, y = price_per_carat, fill = cut)) +
  geom_col() +
  theme_minimal()  # optional, just to improve the look of the plot

diamonds_new <- diamonds %>% 
  mutate(mass_g = .20 * carat,
         price_per_carat = price / carat,
         cut = tolower(cut))

glimpse(diamonds_new)
## Rows: 53,940
## Columns: 12
## $ carat           <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, …
## $ cut             <chr> "ideal", "premium", "good", "premium", "good", "very g…
## $ color           <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, …
## $ clarity         <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI…
## $ depth           <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, …
## $ table           <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54…
## $ price           <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339,…
## $ x               <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, …
## $ y               <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, …
## $ z               <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, …
## $ mass_g          <dbl> 0.046, 0.042, 0.046, 0.058, 0.062, 0.048, 0.048, 0.052…
## $ price_per_carat <dbl> 1417.391, 1552.381, 1421.739, 1151.724, 1080.645, 1400…
diamonds_new <- diamonds %>% 
  mutate(mass_g = .20 * carat,
         price_per_carat = price / carat,
         cut = tolower(cut),
         expensive_TF = price > 10000)

glimpse(diamonds_new)
## Rows: 53,940
## Columns: 13
## $ carat           <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, …
## $ cut             <chr> "ideal", "premium", "good", "premium", "good", "very g…
## $ color           <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, …
## $ clarity         <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI…
## $ depth           <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, …
## $ table           <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54…
## $ price           <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339,…
## $ x               <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, …
## $ y               <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, …
## $ z               <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, …
## $ mass_g          <dbl> 0.046, 0.042, 0.046, 0.058, 0.062, 0.048, 0.048, 0.052…
## $ price_per_carat <dbl> 1417.391, 1552.381, 1421.739, 1151.724, 1080.645, 1400…
## $ expensive_TF    <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…

other usful verbs

?slice_max
?bind_rows
?left_join
?rename
?case_when

group summaries with group_by and summaries

diamonds %>% 
  
group_by(cut) %>% 
  summarise(mean(price))
## # A tibble: 5 × 2
##   cut       `mean(price)`
##   <ord>             <dbl>
## 1 Fair              4359.
## 2 Good              3929.
## 3 Very Good         3982.
## 4 Premium           4584.
## 5 Ideal             3458.

The code will output a summary table with the mean (average) price of diamonds for each unique cut.

diamonds %>% 
  
group_by(cut) %>% 
  summarise(mean_price =mean(price))
## # A tibble: 5 × 2
##   cut       mean_price
##   <ord>          <dbl>
## 1 Fair           4359.
## 2 Good           3929.
## 3 Very Good      3982.
## 4 Premium        4584.
## 5 Ideal          3458.
diamonds %>% 
  group_by(cut) %>% 
  summarise(mean_price =mean(price),
            s_d = sd(price))
## # A tibble: 5 × 3
##   cut       mean_price   s_d
##   <ord>          <dbl> <dbl>
## 1 Fair           4359. 3560.
## 2 Good           3929. 3682.
## 3 Very Good      3982. 3936.
## 4 Premium        4584. 4349.
## 5 Ideal          3458. 3808.

This code provides insights into the average price and the variability (spread) of prices for each combination of diamond cut and color

diamonds %>% 
  group_by(cut,color) %>% 
  summarise(mean_price =mean(price),
            s_d = sd(price))
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
## # A tibble: 35 × 4
## # Groups:   cut [5]
##    cut   color mean_price   s_d
##    <ord> <ord>      <dbl> <dbl>
##  1 Fair  D          4291. 3286.
##  2 Fair  E          3682. 2977.
##  3 Fair  F          3827. 3223.
##  4 Fair  G          4239. 3610.
##  5 Fair  H          5136. 3886.
##  6 Fair  I          4685. 3730.
##  7 Fair  J          4976. 4050.
##  8 Good  D          3405. 3175.
##  9 Good  E          3424. 3331.
## 10 Good  F          3496. 3202.
## # ℹ 25 more rows
diamonds %>% 
  group_by(cut,color) %>% 
  summarise(mean_price =mean(price),
            s_d = sd(price),
           count= n())
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
## # A tibble: 35 × 5
## # Groups:   cut [5]
##    cut   color mean_price   s_d count
##    <ord> <ord>      <dbl> <dbl> <int>
##  1 Fair  D          4291. 3286.   163
##  2 Fair  E          3682. 2977.   224
##  3 Fair  F          3827. 3223.   312
##  4 Fair  G          4239. 3610.   314
##  5 Fair  H          5136. 3886.   303
##  6 Fair  I          4685. 3730.   175
##  7 Fair  J          4976. 4050.   119
##  8 Good  D          3405. 3175.   662
##  9 Good  E          3424. 3331.   933
## 10 Good  F          3496. 3202.   909
## # ℹ 25 more rows

count only

diamonds %>% 
  count(cut,color)
## # A tibble: 35 × 3
##    cut   color     n
##    <ord> <ord> <int>
##  1 Fair  D       163
##  2 Fair  E       224
##  3 Fair  F       312
##  4 Fair  G       314
##  5 Fair  H       303
##  6 Fair  I       175
##  7 Fair  J       119
##  8 Good  D       662
##  9 Good  E       933
## 10 Good  F       909
## # ℹ 25 more rows
diamonds %>% 
  group_by(expencive = price > 10000) %>% 
  summarise(avarige_price =mean(price),
            s_d = sd(price),
           count= n())
## # A tibble: 2 × 4
##   expencive avarige_price   s_d count
##   <lgl>             <dbl> <dbl> <int>
## 1 FALSE             2892. 2400. 48718
## 2 TRUE             13640. 2518.  5222
get_dupes(diamonds,cut) %>% 
  summarise(cut)
## Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in
## dplyr 1.1.0.
## ℹ Please use `reframe()` instead.
## ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()`
##   always returns an ungrouped data frame and adjust accordingly.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## # A tibble: 53,940 × 1
##    cut  
##    <ord>
##  1 Ideal
##  2 Ideal
##  3 Ideal
##  4 Ideal
##  5 Ideal
##  6 Ideal
##  7 Ideal
##  8 Ideal
##  9 Ideal
## 10 Ideal
## # ℹ 53,930 more rows