1
votes

Fonction de boucle qui a trois arguments, les boucles mapply / sapply / for ne fonctionnent pas?

J'essaye de boucler sur une fonction qui a trois arguments, mais ni lapply ni mapply ne fournissent la bonne solution. Le but ici est d'obtenir tous les résultats possibles en fonction de toutes les combinaisons possibles des trois arguments ( num , resp , cdr ). Si vous voyez la fonction ci-dessous, le but ici est de calculer n pour les trois niveaux de num (en maintenant les constantes resp et cdr ), pour les trois niveaux de resp (en maintenant num et cdr constantes), et pour les trois niveaux de cdr (en maintenant resp et num constantes). Mais comme vous pouvez le voir à partir des résultats, ni lapply ni mapply ne fournissent les bonnes réponses ici.

J'ai essayé de le faire avec des boucles for imbriquées sans succès non plus (même si je ne suis pas très doué pour utiliser des boucles, je suis donc ouvert à une solution basée sur les boucles si cela me permet bonne réponse).

Exemple reproductible au minimum:

set.seed(124)
num <- c(10, 20, 30)
resp <- sample(100:200, 3)
cdr <- 3:5

my_fun <- function(num, resp, cdr){
 n <- ((num * resp) / cdr)   
}  

sapply(num, my_fun, resp, cdr)
     [,1] [,2] [,3]
[1,]  360  720 1080
[2,]  350  700 1050
[3,]  302  604  906

mapply(my_fun, num, resp, cdr)
[1] 360 700 906


5 commentaires

Peut-être expand.grid (num, resp, cdr) ?


@ H1 a exécuté expand.grid (num, resp, cdr) mais pour autant que je sache, il n'applique pas la fonction pour obtenir un calcul de n pour chacun des 27 combinaisons?


@rowbust Je ne suis pas sûr de ce que votre résultat attendu est censé être (par exemple un tableau 3D, un data.frame aplati, ...?). Pouvez-vous modifier votre message pour l'inclure?


@ H1 signifiait simplement que expand.grid () vous donnerait les 27 combinaisons, sur lesquelles vous pourriez ensuite utiliser mapply (ou quelque chose d'équivalent) correctement.


@rowbust BTW Assurez-vous que votre fonction renvoie quelque chose.


3 Réponses :


4
votes

Vous pouvez essayer:

df <- expand.grid(data.frame(num, resp, cdr))
with(df, (num * resp) / cdr)

   num resp cdr         n
1   10  151   3  503.3333
2   20  151   3 1006.6667
3   30  151   3 1510.0000
4   10  176   3  586.6667
5   20  176   3 1173.3333
...


1 commentaires

Cela semble également fonctionner do.call (my_fun, expand.grid (data.frame (num, resp, cdr))) +1



0
votes
# gen data
set.seed(124)
num  <- c(10, 20, 30)
resp <- sample(100:200, 3)
cdr  <- 3:5

# function (written with one input vector)
my_fun <- function(x){
  x[1] * x[2] / x[3]  
} 

# used expand.grid() and apply() to 
# eval function on all combos of num, resp, cdr
opts <- expand.grid(num, resp, cdr)
res  <- apply(opts, 1, my_fun)
cbind(opts, res)

4 commentaires

apply ne semble pas être une bonne option car la fonction de OP est vectorisée dans ses arguments.


Puis juste: opts <- expand.grid (num, resp, cdr); my_fun (opts [1], opts [2], opts [3]) avec la définition de l'OP de my_fun .


Oui! Consultez do.call - très utile (et efficace) dans de tels cas.


Oui - franchement, malgré mon message, j'aime mieux la solution de @markus avec do.call ()



2
votes

Une solution basée sur purrr / dplyr serait:

set.seed(124)
num <- c(10, 20, 30)
resp <- sample(100:200, 3)
cdr <- 3:5

my_fun <- function(num, resp, cdr){
 ((num * resp) / cdr)   
} 

args <- list(num = num, resp = resp, cdr = cdr)
args %>% 
  purrr::cross_df() %>% 
  dplyr::mutate(res = my_fun(num, resp, cdr))


0 commentaires