Home > Software design >  R - using set_names in map fails
R - using set_names in map fails

Time:11-13

First let's create an example directory on which this example is ran:

c("Level1/Level1A/Level1AA", 
  "Level1/Level1A/Level1AB", 
  "Level1/Level1B/Level1BA", 
  "Level1/Level1B/Level1BB",
  "Level2/Level2A/Level2AA", 
  "Level2/Level2A/Level2AB", 
  "Level2/Level2B/Level2BA", 
  "Level2/Level2B/Level2BB") %>% 
  map(dir.create, recursive = T)

What I would like is to get a named nested list which mirrors this folder structure. It obligatory has to be in tidyverse style. I am trying to build it bit by bit. The first part of my code seems to work well:

list.dirs(recursive = F) %>% 
  map(list.dirs, recursive = F) %>% 
  set_names(str_split(., "/") %>% 
              map(pluck, 2))

The output is the following:

$Level1
[1] "./Level1/Level1A" "./Level1/Level1B"

$Level2
[1] "./Level2/Level2A" "./Level2/Level2B"

So we can see that the list element names are indeed Level1 and Level2, as expected. In the next step, I want to create the next sublevel of the list. However, my code fails:

list.dirs(recursive = F) %>% 
  map(list.dirs, recursive = F) %>% 
  set_names(str_split(., "/") %>% 
              map(pluck, 2)) %>% 
  map_depth(2, list.dirs, recursive = F) %>% 
  map(set_names, str_split(., "/") %>% 
        map_depth(2, pluck, 3))

The output is as follows:

$Level1
$Level1$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level1/Level1A/Level1AA" "./Level1/Level1A/Level1AB"

$Level1$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level1/Level1B/Level1BA" "./Level1/Level1B/Level1BB"


$Level2
$Level2$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level2/Level2A/Level2AA" "./Level2/Level2A/Level2AB"

$Level2$`list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)`
[1] "./Level2/Level2B/Level2BA" "./Level2/Level2B/Level2BB"

So the problem is that, for example, the first sublevel of the first level of the list is now named list(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) instead of Level1A.

I don't understand why this happens.

How is my code supposed to look like?

Please the answer has to be pipe-friendly. Thank you.

EDIT: The structure which I desire is the following:

list(Level1 = list(Level1A = c("Level1AA", "Level1AB"),
                        Level1B = c("Level1BA", "Level1BB")),
     Level2 = list(Level2A = c("Level2AA", "Level2AB"),
                        Level2B = c("Level2BA", "Level2BB")))

CodePudding user response:

Are you looking for something along these lines?

library(tidyverse)

list.dirs(recursive = FALSE) |>
  map(\(.x) map(.x, 
                \(.y) list.dirs(path = .y, recursive = FALSE)) |>
        set_names(str_extract(.x, "(?<=/)\\w (?=$)"))) |>
  map(\(.x) map(.x, 
                \(.y) map(.y, 
                          \(.z) list.dirs(path = .z, recursive = FALSE) |>
                           str_extract("(?<=/)\\w (?=$)")) |>
              set_names(str_extract(.y, "(?<=/)\\w (?=$)"))))
#> [[1]]
#> [[1]]$Level1
#> [[1]]$Level1$Level1A
#> [1] "Level1AA" "Level1AB"
#> 
#> [[1]]$Level1$Level1B
#> [1] "Level1BA" "Level1BB"
#> 
#> 
#> 
#> [[2]]
#> [[2]]$Level2
#> [[2]]$Level2$Level2A
#> [1] "Level2AA" "Level2AB"
#> 
#> [[2]]$Level2$Level2B
#> [1] "Level2BA" "Level2BB"

EDIT updated for desired output:

list.dirs(recursive = FALSE) |>
  map(\(.x) list.dirs(path = .x, recursive = FALSE) ) |>
  set_names(str_extract(list.dirs(recursive = FALSE), "(?<=/)\\w (?=$)")) |>
  map(\(.x) map(.x, \(.y) list.dirs(path = .y, recursive = FALSE)|>
                           str_extract("(?<=/)\\w (?=$)")) |>
        set_names(str_extract(.x, "(?<=/)\\w (?=$)"))) 
#> $Level1
#> $Level1$Level1A
#> [1] "Level1AA" "Level1AB"
#> 
#> $Level1$Level1B
#> [1] "Level1BA" "Level1BB"
#> 
#> 
#> $Level2
#> $Level2$Level2A
#> [1] "Level2AA" "Level2AB"
#> 
#> $Level2$Level2B
#> [1] "Level2BA" "Level2BB"
  •  Tags:  
  • r
  • Related