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
Control Point Border Thickness in Ggplot
Recommendations for Windows Text Editor for R
Rvest Error in Open.Connection(X, "Rb"):Timeout Was Reached
Getting the Last N Elements of a Vector. Is There a Better Way Than Using the Length() Function
Merge Three Different Columns into a Date in R
Include Space for Missing Factor Level Used in Fill Aesthetics in Geom_Boxplot
No Rtools Compatible with R Version 3.5.0 Was Found
Is There a Vectorized Parallel Max() and Min()
R Displays Numbers in Scientific Notation
Split a String by Any Number of Spaces
Show Names of Everything in a Package
Fast Levenshtein Distance in R
Render Dropdown for Single Column in Dt Shiny
Reordering Factor Gives Different Results, Depending on Which Packages Are Loaded