Je dois accéder aux noms de liste dans la fonction lapply. J'ai trouvé des discussions en ligne où il est dit que je devrais parcourir les noms de la liste pour pouvoir récupérer chaque nom d'élément de liste dans ma fonction:
> n = names(mylist)
> mynewlist = lapply(n, function(nameindex, mylist) { return(mylist[[nameindex]]) }, mylist)
> names(mynewlist)
NULL
> names(mynewlist) = n
Le problème est que mynewlist perd les index mylist d'origine et je dois ajouter cette affectation last names () pour les restaurer.
Est-il possible de donner un nom d'index explicite à chaque élément renvoyé par la fonction lapply? Ou une autre façon de vous assurer que les éléments de la nouvelle liste ont les noms d'index corrects? Je pense que les noms d’index de ma nouvelle liste pourraient être erronés si lapply ne renvoie pas les éléments de la liste dans le même ordre que mylist.
Je crois que lapply
par défaut conserve l'attribut de noms de ce que vous parcourez. Lorsque vous stockez les noms de myList
dans n
, ce vecteur ne comporte plus de "noms". Donc, si vous rajoutez cela via,
names(n) <- names(myList)
et utilisez lapply
comme précédemment, vous devriez obtenir le résultat souhaité.
Modifier
Mon cerveau un peu brumeux ce matin. Voici une autre option, peut-être plus pratique:
sapply(n,FUN = ...,simplify = FALSE,USE.NAMES = TRUE)
J'étais à tâtons, confus que lapply
n'avait pas d'argument USE.NAMES
, puis j'ai regardé le code pour sapply
et me suis rendu compte que j'étais ridicule et que c'était probablement une meilleure façon de faire.
la fonction setNames
est un raccourci utile ici
mylist <- list(a = TRUE, foo = LETTERS[1:3], baz = 1:5)
n <- names(mylist)
mynewlist <- lapply(setNames(n, n), function(nameindex) {mylist[[nameindex]]})
qui conserve les noms
> mynewlist
$a
[1] TRUE
$foo
[1] "A" "B" "C"
$baz
[1] 1 2 3 4 5
Avez-vous examiné llply()
dans le package plyr
?
Il fait exactement ce que vous demandez. Pour chaque élément d'une liste, appliquez une fonction en conservant les résultats sous forme de liste. llply est équivalent à lapply, sauf qu'il conservera les étiquettes et peut afficher une barre de progression. de ?llply
mylist <- list(foo1=1:10,foo2=11:20)
>names(mylist)
[1] "foo1" "foo2"
newlist<- llply(mylist, function(x) mean(x))
>names(newlist)
[1] "foo1" "foo2"
S'appuyant sur la réponse de Joran et la précisant:
Le wrapper sapply(USE.NAMES=T)
définira en effet comme noms du résultat final les valeurs du vecteur sur lequel vous effectuez une itération (et non son attribut names comme lapply), mais uniquement s'il s'agit de caractères.
En conséquence, les indices de passage ne vont pas aider. Si vous voulez passer des index avec sapply
, vous devez recourir à un casting (laid):
sapply(as.character(c(1,11)), function(i) TEST[[as.numeric(i)]], USE.NAMES = TRUE)
Dans ce cas, une solution plus propre consiste à définir et à utiliser directement les noms de votre objet d'origine. Voici une liste exhaustive de solutions:
TEST <- as.list(LETTERS[1:12])
### lapply ##
## Not working because no name attribute
lapply(c(1,11), function(i) TEST[[i]])
## working but cumbersome
index <- c(1,11)
names(index) <- index
lapply(index, function(i) TEST[[i]])
### sapply ##
## Not working because vector elements are not strings
sapply(c(1,11), function(i) TEST[[i]], simplify = F)
## Working with the casting trick
sapply(as.character(c(1,11)), function(i) TEST[[as.numeric(i)]], simplify = F)
## Cleaner, using names with sapply:
names(TEST) <- LETTERS[26:15]
sapply(names(TEST)[c(1,11)], function(name) TEST[[name]], simplify = F)
imap()
du paquet purrr
convient à votre problème.
library(purrr)
mylist <- list(foo1=1:10,foo2=11:20)
imap(mylist, function(x, y) mean(x)) ## x is the value, y is the name
ou vous pouvez utiliser une version plus compacte de imap:
imap(mylist, ~ mean(.x))
Notez que vous pouvez utiliser des variantes de imap_xxx en fonction du type de vecteur souhaité:
imap_dbl(mylist, ~ mean(.x)) ## will return a named numeric vector.