How to use parameters from data frame in R and loop through time holding them constant

71 views Asked by At

I have a function (weisurv) that has 2 parameters - sc and shp. It is a function through time (t). Time is a sequence, i.e. t<-seq(1:100).

weisurv<-function(t,sc,shp){
surv<-exp(-(t/sc)^shp)
return(surv)
}

I have a data frame (df) that contains a list of sc and shp values (like 300+ of them). For example, I have:

     M       shp     sc      p  C i
1    1  1.138131 10.592154 0.1  1 1
2 1.01  1.143798 10.313217 0.1  1 2
3 1.02  1.160653 10.207863 0.1  1 3
4 1.03  1.185886  9.861997 0.1  1 4
...

I want to apply each set (ROW) of sc and shp parameters to my function. So the function would look like weisurv(t,sc[[i]],shp[i]]) for each row[i]. I do not understand how to use apply or adply to do this though I'm sure one of these or a combo of both are what is needed. In the end, I am looking for a data frame that gives a value of weisurv for each time given a set of sc and shp (held constant through time). So if I had 10 sets of sc and shp parameters, I would end up with 10 time series of weisurv. Thanks....

2

There are 2 answers

7
Nick Kennedy On BEST ANSWER

Using plyr:

As a matrix (time in cols, rows corresponding to rows of df):

aaply(df, 1, function(x) weisurv(t, x$sc, x$shp), .expand = FALSE)

As a list:

alply(df, 1, function(x) weisurv(t, x$sc, x$shp))

As a data frame (structure as per matrix above):

adply(df, 1, function(x) setNames(weisurv(t, x$sc, x$shp), t))

As a long data frame (one row per t/sc/shp combination); note uses mutate and the pipe operator from dplyr):

newDf <- data.frame(t = rep(t, nrow(df)), sc = df$sc, shp = df$shp) %>%
  mutate(surv = weisurv(t, sc, shp))

You can also create a wide data.frame and then use reshape2::melt to reformat as long:

wideDf <- adply(df, 1, function(x) setNames(weisurv(t, x$sc, x$shp), t))
newDf <- melt(wideDf, id.vars = colnames(df), variable.name = "t", value.name = "surv")
newDf$t <- as.numeric(as.character(newDf$t))

Pretty plot of last newDf (using ggplot2):

ggplot(newDf, aes(x = t, y = surv, col = sprintf("sc = %0.3f, shp = %0.3f", sc, shp))) +
geom_line() +
scale_color_discrete(name = "Parameters")

ggplot image of weisurv output

0
tegancp On

Not sure about the exact structure you want in the final dataframe... and I think there must be a cleaner way to do this, but this should work.

option 1 rows are the same as your df, with new columns t<n> for each value of t:

for(n in t){
    df$temp <- weisurv(n, df$sc, df$shp)
    names(df)[n+2] <- paste0('t', n)
}

option 2 long dataframe, with columns sc, shp, t, and weisurv(t,sc,shp):

l = length(t)
newdf <- data.frame(sc=rep(df$sc, each=l), shp=rep(df$shp, each=l),
    t=rep(t, times=nrow(df)) )
newdf$weisurv <- weisurv(newdf$t, newdf$sc, newdf$shp)