voglio usare dplyr per eseguire simulazioni su griglie di parametri. Specificamente, vorrei una funzione che posso utilizzare in un altro programma che
- viene passato un data.frame
- per ogni riga calcola una simulazione utilizzando ogni colonna come argomento
- anche è passato un certo dati aggiuntivi (ad esempio, condizioni iniziali)
Ecco il mio approccio
require(dplyr)
run <- function(data, fun, fixed_parameters, ...) {
## ....
## argument checking
##
fixed_parameters <- as.environment(fixed_parameters)
grouped_out <- do_(rowwise(data), ~ do.call(fun, c(., fixed_parameters, ...)))
ungroup(grouped_out)
}
Th è un lavoro. Ad esempio, per
growth <- function(n, r, K, b) {
# some dynamical simulation
# this is an obviously-inefficient way to do this ;)
n + r - exp(n)/K - b - rnorm(1, 0, 0.1)
}
growth_runner <- function(r, K, b, ic, ...) {
# a wrapper to run the simulation with some fixed values
n0 = ic$N0
T = ic$T
reps = ic$reps
data.frame(n_final = replicate(reps, {for(t in 1:T) {
n0 <- growth(n0, r, K, b)
};
n0})
)
}
posso definire ed eseguire,
data <- expand.grid(b = seq(0.01, 0.5, length.out=10),
K = exp(seq(0.1, 5, length.out=10)),
r = seq(0.5, 3.5, length.out=10))
initial_data = list(N0=0.9, T=5, reps=20)
output <- run(data, growth_runner, initial_data)
Domanda
Anche se questo sembra funzionare, mi chiedo se c'è un modo per farlo senza do.call
. (In parte a causa di issues with do.call.)
Sono davvero interessato a un modo per sostituire la riga grouped_out <- do_(rowwise(data), ~ do.call(fun, c(., fixed_parameters, ...)))
con qualcosa che fa la stessa cosa ma senza do.call
. Modifica: Un approccio che evita in qualche modo le penalizzazioni delle prestazioni dell'utilizzo di do.call
descritto nel collegamento sopra funzionerebbe anche.
note e riferimenti
- this question on do.call and standard evaluation in dplyr è utile, ma sto cercando un modo per evitare, se possibile, do.call
- di dplyr nse vignette era utile nello scrivere questo; e mi fa pensare
.values
potrebbe funzionare in luogo dido.call
FWIW sembra esattamente come 'plyr :: mdply'. Sfortunatamente i due pacchetti sono piuttosto incompatibili. – baptiste
dang, non avrei mai trovato quella parte di 'plyr'! grazie per il puntatore – jaimedash
Penso che probabilmente si voglia 'purrr :: invoke_rows' per questo, è l'equivalente moderno di' mdply'. http://rpackages.ianhowson.com/cran/purrr/man/by_row.html – Shorpy