2 votes

Fusionner et encadrer plusieurs listes similaires par les noms des éléments, lorsqu'un élément comprend une fonction.

J'ai plusieurs listes avec la même structure (mêmes éléments de liste, valeurs différentes), et je veux lier les listes à l'aide de la fonction dplyr::bind_rows() . Je rencontre une erreur car l'un des éléments de la liste est une fonction.

Exemple

lst_a <- list(what_it_does = "adds 1", func = function (x) x + 1)
lst_b <- list(what_it_does = "subtracts 2", func = function(x) x - 2)
lst_c <- list(what_it_does = "takes a sqrt", func = function (x) sqrt(x))
lst_d <- list(what_it_does = "multiplies by 5", func = function (x) x * 5)

Sortie souhaitée Combiner les listes en un seul tableau (tibble)

# A tibble: 4 x 3
name   what_it_does    func  
<chr>  <chr>           <list>
lst_a  adds 1          <fn>  
lst_b  subtracts 2     <fn>  
lst_c  takes a sqrt    <fn>  
lst_d  multiplies by 5 <fn> 

Ma tentative
Au début, j'ai essayé :

library(dplyr)

bind_rows(lst_a, lst_b, lst_c, lst_d)

Erreur : L'entrée doit être un vecteur, pas une fonction.

Puis j'ai pensé que je devrais peut-être emballer les func dans chaque liste à l'intérieur de son propre list() ce qui fonctionne :

lst_a_wrapped <- list(what_it_does = "adds 1", func = list(function (x) x + 1))
lst_b_wrapped <- list(what_it_does = "subtracts 2", func = list(function(x) x - 2))
lst_c_wrapped <- list(what_it_does = "takes a sqrt", func = list(function (x) sqrt(x)))
lst_d_wrapped <- list(what_it_does = "multiplies by 5", func = list(function (x) x * 5))

bind_rows(lst_a_wrapped, lst_b_wrapped, lst_c_wrapped, lst_d_wrapped)

## # A tibble: 4 x 2
##   what_it_does    func  
##   <chr>           <list>
## 1 adds 1          <fn>  
## 2 subtracts 2     <fn>  
## 3 takes a sqrt    <fn>  
## 4 multiplies by 5 <fn>  

Mon problème
Considérez que je peux avoir beaucoup de listes à compiler, donc envelopper manuellement chaque func dans chaque liste avec un élément interne list() est inélégante. Existe-t-il un moyen d'aller directement (c'est-à-dire par programme) de { lst_a , lst_b , lst_c , lst_d } à la sortie souhaitée ? D'après ce que j'ai pu trouver, bind_rows() n'a pas d'arguments supplémentaires pour modifier l'entrée, donc la solution doit être autre.

Bonus. Bien que ce ne soit pas trop important, je serais heureux d'apprendre également s'il existe un moyen d'obtenir une name comme dans le résultat souhaité, dérivé des listes de noms d'objets, dans le cadre du processus.

2voto

GKi Points 6744

Vous pouvez ajouter le list autour de la fonction dans une boucle comme :

x <- mget(c("lst_a", "lst_b", "lst_c", "lst_d"))
y <- lapply(x, function(x) lapply(x, function(y) if(is.function(y)) list(y) else y))
dplyr::bind_rows(y)
## A tibble: 4 x 2
#  what_it_does    func  
#  <chr>           <list>
#1 adds 1          <fn>  
#2 subtracts 2     <fn>  
#3 takes a sqrt    <fn>  
#4 multiplies by 5 <fn>

1voto

Jakub.Novotny Points 2087

Si vous avez de nombreuses listes avec un préfixe commun tel que "lst_", vous pouvez envisager d'utiliser la méthode suivante ls fonction.

all_lsts <- mget(ls(pattern = "^lst_"))

all_lsts_fixed <- lapply(all_lsts, function(x) lapply(x, function(y) if(is.function(y)) list(y) else y))

dplyr::bind_rows(all_lsts_fixed)

# # A tibble: 4 x 2
# what_it_does    func  
# <chr>           <list>
#   1 adds 1          <fn>  
#   2 subtracts 2     <fn>  
#   3 takes a sqrt    <fn>  
#   4 multiplies by 5 <fn>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X