Karottensticks
Karottensticks

Reputation: 23

R loop over a function argument to add variables to data frame

I am new to R and after hours of trying and searching for answers in similar questions, I still cannot figure out how to loop the following code over the integer n rather than writing one line for each n.

d <- data.frame(s = seq(0, 0.125, 0.001))
f <- function(n, s, x) {
    (1 - 2*sqrt(2*s) + x)^(n - 1)*(1 - 2*sqrt(2*s) + (1 + n)*x) - 1)
}

d <- d %>% 
    mutate(p_2 = mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=2,d$s),
           p_3 = mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=3,d$s),
           p_4 = mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=4,d$s),
           p_5 = mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=5,d$s))

The following does repeatedly print the variable I am trying to add to my data frame d,

for (i in c(2:10)){
mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=i,d$s) %>% print()
}

but when I then try to use this with the mutate function inside the loop, only one new variable is added to the data frame under the name "p_i" which takes on the values of what would be "p_10":

for (i in 2:10){
    d <- d %>% mutate(p_i = mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=i,d$s))
}

How do I get R to loop through n and append a new variable for each iteration? Apologies if I am missing an obvious mistake or would not need to use a for loop at all to make this work. Any help would be greatly appreciated to get unstuck.

Upvotes: 2

Views: 619

Answers (1)

dww
dww

Reputation: 31452

You can do this simply enough in base R. No need to complicate things with mutate

for (i in c(2:10)){
  d[[paste0('p_', i)]] = 
    mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=i,d$s) 
}

Note that if you really want to use dplyr, then you can combine !! and := to achieve the desired result. But I find the base R much neater and simpler.

for (i in 2:10){
  d <- d %>% mutate(!!paste0('p_', i) := 
                      mapply(function(n,s) uniroot(f, interval = c(0,1),n=n,s=s)$root,n=i,d$s))
}

Upvotes: 3

Related Questions