Unexpected output of set_names()
- I'm trying to name a list of tibbles using
set_names
. - I expect the names to be
"tbl_df, tbl, data.frame"
- However, the result is
"character"
.
Any ideas why?
library(tidyverse)
l1 <- # Small list of short tibbles
diamonds |>
group_split(cut) |>
map(~ .x |> slice(1:2)) |>
head(2)
l1 |> # Trying to name them based on their class, but the result is "character" which is wrong:
set_names(function(x) class(x) |> paste(collapse = ", "))
#> $character
#> # A tibble: 2 × 10
#> carat cut color clarity depth table price x y z
#> <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#> 1 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49
#> 2 0.86 Fair E SI2 55.1 69 2757 6.45 6.33 3.52
#>
#> $character
#> # A tibble: 2 × 10
#> carat cut color clarity depth table price x y z
#> <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#> 1 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
#> 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
# Evidence that each element should be named "tbl_df, tbl, data.frame", not character
l1[[1]] |>
class() |>
paste(collapse = ", ")
#> [1] "tbl_df, tbl, data.frame"
Created on 2025-03-13 with reprex v2.1.1
Unexpected output of set_names()
- I'm trying to name a list of tibbles using
set_names
. - I expect the names to be
"tbl_df, tbl, data.frame"
- However, the result is
"character"
.
Any ideas why?
library(tidyverse)
l1 <- # Small list of short tibbles
diamonds |>
group_split(cut) |>
map(~ .x |> slice(1:2)) |>
head(2)
l1 |> # Trying to name them based on their class, but the result is "character" which is wrong:
set_names(function(x) class(x) |> paste(collapse = ", "))
#> $character
#> # A tibble: 2 × 10
#> carat cut color clarity depth table price x y z
#> <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#> 1 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49
#> 2 0.86 Fair E SI2 55.1 69 2757 6.45 6.33 3.52
#>
#> $character
#> # A tibble: 2 × 10
#> carat cut color clarity depth table price x y z
#> <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#> 1 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
#> 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
# Evidence that each element should be named "tbl_df, tbl, data.frame", not character
l1[[1]] |>
class() |>
paste(collapse = ", ")
#> [1] "tbl_df, tbl, data.frame"
Created on 2025-03-13 with reprex v2.1.1
Share Improve this question asked Mar 13 at 9:19 Rasmus LarsenRasmus Larsen 6,16910 gold badges51 silver badges80 bronze badges 1 |3 Answers
Reset to default 2The issue is that R is not passing each element of l1
to your function - it's passing the names of the elements. But your list doesn't have names yet -> R is creating temporary names which are of type "character"
, and that's what's being passed to your function. there might be better ways, but you can try
library(tidyverse)
l1 <- diamonds |> group_split(cut) |> map(~ .x |> slice(1:2)) |> head(2)
setNames(l1, map_chr(l1, ~paste(class(.x), collapse = ", ")))
$`tbl_df, tbl, data.frame`
# A tibble: 2 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49
2 0.86 Fair E SI2 55.1 69 2757 6.45 6.33 3.52
$`tbl_df, tbl, data.frame`
# A tibble: 2 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
Use lapply
:
l1 |>
set_names(lapply(l1, \(x) class(x) |> paste(collapse=", ")))
$`tbl_df, tbl, data.frame`
# A tibble: 2 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49
2 0.86 Fair E SI2 55.1 69 2757 6.45 6.33 3.52
$`tbl_df, tbl, data.frame`
# A tibble: 2 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
R
vanilla
l =
ggplot2::diamonds |>
split(~cut) |>
lapply(head, 2) |>
head(2)
We do not need paste(, collapse='')
as suggested in User Tim G's answer, we have toString()
.
All classes equal, then
setNames(l, rep(toString(class(l[[1]])), length(l)))
# names(l) = rep(toString(class(l[[1]])), length(l))
Differences, then
setNames(l, sapply(l, \(n) toString(class(n))))
# names(l) = sapply(l, \(n) toString(class(n)))
$`tbl_df, tbl, data.frame`
# A tibble: 2 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49
2 0.86 Fair E SI2 55.1 69 2757 6.45 6.33 3.52
$`tbl_df, tbl, data.frame`
# A tibble: 2 × 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
Why would one do this?
l1
to your function - it's passing the names of the elements. But your list doesn't have names yet -> R is creating temporary names which are of type "character", and that's what's being passed to your function. there might be better ways, but you can trysetNames(l1, map_chr(l1, ~paste(class(.x), collapse = ", ")))
– Tim G Commented Mar 13 at 9:25