I am trying to simulate fitted values for changing models of different subgroups of my data, which again are based on random sampling of another subset of my original data frame (the minimal example I made up for this question ignores the random sampling etc., resulting in identical fitted values for all simulations, but that doesn't matter). I have written a dplyr-code to store the model for each group, produce new x-values for predicting fitted values, predict them etc. etc. It results in one column of fitted values, exactly as I want it. However, I would like to go through the whole process 1000x. I can of course do this with a for-loop (as done below in the example), but is there a possibility to do such a thing within a dplyr-pipe line? And maybe speed the whole process up a bit (my original data set is rather large and the for-loop takes forever)?
# making up data
dat <- data.frame("species" = seq(1:20), "col_A" = runif(20, min=1000, max=2500), "col_B" = runif(20, min = 0, max = 1500),
"maximum" = rep(2500, 20), "minimum" = rep(1000, 20), groups = rep(LETTERS[1:5], each = 4))
# functions to use with purrr
linear_mod <- function(dat) {
lm(col_A ~ col_B, data = dat)
}
# define parametres and an empty data frame to use in the for loop
runs <- 10
fitted_sim <- data.frame(matrix(data=NA,nrow=20,ncol=runs+1,byrow=FALSE)) #empty dataframe to contain fitted values for each alt
names(fitted_sim) <- as.factor(seq(1:runs+1))
# for-loop around my dplyr-code
for (j in 1:runs){
simul <- dat %>%
group_by(groups) %>%
nest(data = c(col_A, col_B, species)) %>%
mutate(model = map(data, linear_mod), # add model for every group
sim_data = list(seq(minimum, maximum, by = 10))) %>% # define new x-values for later predictions
unnest(sim_data) %>%
nest(sim_data = sim_data) %>%
mutate(fitted = map2(model, sim_data, ~predict(.x, col_B = sim_data, type = "response")), # predict values
unnest(fitted) # unnest predicted values to save in data frame
# save newly fitted values in fitted_sim data frame
fitted_sim[,1] <- simul$groups
fitted_sim[,1+j] <- simul$fitted
}
Thanks for every hint!
EDIT: This is an extended example code including the random sampling described above but omitted in my first example:
# for-loop around my dplyr-code
for (j in 1:runs) {
simul <- dat %>%
group_by(groups) %>%
rowwise() %>%
mutate(vector_column = case_when(abs(col_A) == (maximum-minimum) ~ list(col_B),
sign(col_A) == 1 ~ list(dat$col_B[dat$col_B <= maximum - col_A]), # using list function to store vectors in a data.frame
sign(col_A) != 1 ~ list(dat$col_B[dat$col_B >= minimum + col_A])),
helper = !is_empty(vector_column), # in case some of the vectors are empty so it is not possible to use sample
col_B_new = ifelse(helper, sample(vector_column, 1), NA),
helper = NULL,
sim_data = list(seq(minimum, maximum, by = 10))) %>% # define new x-values for later predictions
ungroup() %>% # get rid of rowwise()
group_by(groups) %>%
unnest(sim_data) %>%
nest(sim_data = sim_data) %>%
nest(data = c(col_A, col_B, col_B_new, species)) %>%
mutate(model = map(data, linear_mod),
fitted = map2(model, sim_data, ~predict(.x, col_B_new = sim_data, type = "response"))) %>% # predict values
unnest(fitted) # unnest predicted values to save in data frame
# save newly fitted values in fitted_sim data frame
fitted_sim[,1] <- simul$groups
fitted_sim[,1+j] <- simul$fitted
}