Access and Preserve List Names in Lapply Function

Access and preserve list names in lapply function

I believe that lapply by default keeps the names attribute of whatever you are iterating over. When you store the names of myList in n, that vector no longer has any "names". So if you add that back in via,

names(n) <- names(myList)

and the use lapply as before, you should get the desired result.

Edit

My brains a bit foggy this morning. Here's another, perhaps more convenient, option:

sapply(n,FUN = ...,simplify = FALSE,USE.NAMES = TRUE)

I was groping about, confused that lapply didn't have a USE.NAMES argument, and then I actually looked at the code for sapply and realized I was being silly, and this was probably a better way to go.

Access lapply index names inside FUN

Unfortunately, lapply only gives you the elements of the vector you pass it.
The usual work-around is to pass it the names or indices of the vector instead of the vector itself.

But note that you can always pass in extra arguments to the function, so the following works:

x <- list(a=11,b=12,c=13) # Changed to list to address concerns in commments
lapply(seq_along(x), function(y, n, i) { paste(n[[i]], y[[i]]) }, y=x, n=names(x))

Here I use lapply over the indices of x, but also pass in x and the names of x. As you can see, the order of the function arguments can be anything - lapply will pass in the "element" (here the index) to the first argument not specified among the extra ones. In this case, I specify y and n, so there's only i left...

Which produces the following:

[[1]]
[1] "a 11"

[[2]]
[1] "b 12"

[[3]]
[1] "c 13"

UPDATE Simpler example, same result:

lapply(seq_along(x), function(i) paste(names(x)[[i]], x[[i]]))

Here the function uses "global" variable x and extracts the names in each call.

preserve list elements as names in lapply function

You could try

 added <- setNames(added, seq)

Or

 names(added) <- seq

Can a named list be returned from lapply function in R?

We can use setNames

output <- setNames(output, unique(unlist(output)))
str(output)
#List of 3
# $ a:List of 2
# ..$ x: chr "a"
# ..$ y: chr "a"
# $ b:List of 2
# ..$ x: chr "b"
# ..$ y: chr "b"
# $ c:List of 2
# ..$ x: chr "c"
# ..$ y: chr "c"

If we start from the beginning, it can be named vector

output <- lapply(setNames(vect, vect), function(list_member){
list(x = list_member, y = list_member)
})

naming elements inside list using lapply

We can use Map to loop through the names of 'my_list' and the list itself, then use setNames to name the individual nested list elements

Map(function(x, y) setNames(x, paste0(y, seq_along(x)))
, my_list, names(my_list))

A similar option using tidyverse would be

library(purrr)
map2(my_list, names(my_list), ~ set_names(.x, paste0(.y, seq_along(.x))))

Or instead of map2, imap get the names of the list as .y (as @Moody_Mudskipper commented)

imap(my_list, ~ set_names(.x, paste0(.y, seq_along(.x))))

Access names of list elements in a loop

In the purrr package, there are the functions imap() and iwalk(). They take a list and a function with two arguments and apply the function to every element of the list and its index/name. The difference is, that iwalk silently returns NULL and is executed only for side effects (helpful if you map over cat()) and imap() works similar to lapply() only it uses the functions second argument for the list's names.

library(purrr)
lst <- list(a1 = 5:12, b4 = c(34,12,5), c3 = 23:45)

imap(lst,\(x,y) cat("The name of the current list element is", y, "\n"))
#> The name of the current list element is a1
#> The name of the current list element is b4
#> The name of the current list element is c3
#> $a1
#> NULL
#>
#> $b4
#> NULL
#>
#> $c3
#> NULL

iwalk(lst,\(x,y) cat("The name of the current list element is", y, "\n"))
#> The name of the current list element is a1
#> The name of the current list element is b4
#> The name of the current list element is c3

Created on 2022-01-18 by the reprex package (v2.0.1)

How to naming list elements using only lapply in R

The second argument of lappyl() has to be a function. One can use setNames():

named_list <- lapply(l, setNames, nm=mynames)
named_list[1:2]
[[1]]
[[1]]$`number one`
[1] 1 2 3

[[1]]$`number two`
[1] 1 2 3


[[2]]
[[2]]$`number one`
[1] 1 2 3

[[2]]$`number two`
[1] 1 2 3

An alternative version based on the replacement function `names<-` is:

named_list2 <- lapply(l, function(x, names) { names(x) <- names; x },
names=mynames)
identical(named_list, named_list2)
[1] TRUE


Related Topics



Leave a reply



Submit