I am running the following code with desolve library. Now, I want to run the same code for different values of koff_WT. PLease suggest any simple way to do that.
kon_WT = 1
koff_WT = 10
R_WT = 20
Complex <- function (t,y,parms){
with(as.list(y), {
dC_WT <- koff_WT*RL_WT -kon_WT*R_WT*C_WT
dRL_WT <- kon_WT*R_WT*C_WT - koff_WT*RL_WT #uM
dR_WT <- koff_WT*RL_WT -kon_WT*R_WT*C_WT
return(list(c(dC_WT, dRL_WT, dR_WT)))
})
}
times <- seq(0,1,0.01)
Out <- ode(y = c(C_WT = 10, RL_WT = 0, R_WT= R_WT),
times = times, func=Complex, parms=NULL)
Output <- data.frame(Out)
You can use a function to define your function Complex()
library("deSolve")
kon_WT = 1
## koff_WT = 10
R_WT = 20
defComplex <- function(koff) {
return( function (t, y, parms) {
with(as.list(y), {
dC_WT <- koff*RL_WT - kon_WT*R_WT*C_WT
dRL_WT <- kon_WT*R_WT*C_WT - koff*RL_WT #uM
dR_WT <- koff*RL_WT - kon_WT*R_WT*C_WT
return(list(c(dC_WT, dRL_WT, dR_WT)))
})
})
}
resC_WT <- function(iC_WT) {
imes <- seq(0,1,0.01)
Out <- ode(y = c(C_WT = iC_WT, RL_WT = 0, R_WT= R_WT), times = times, func=Complex, parms=NULL)
Output <- data.frame(Out)
return(Output[nrow(Output), ])
}
vectorC_WT <- 1:11
Complex <- defComplex(koff=10)
sapply(vectorC_WT, FUN=resC_WT)
Complex <- defComplex(koff=15)
sapply(vectorC_WT, FUN=resC_WT)
This is not very elegant, but it works.
Also you can put the two working lines in a function to use another lapply()-call.
It would be better to use the parms parameter to pass in a list of constants to your complex function. At the moment, it is not doing anything.
If you arrange it that way, you can create a second function that will run your simulation for any value of koff_WT you like:
library(deSolve)
Complex <- function (t ,y, parms){
y <- as.list(y)
list(c(dC_WT = parms$koff_WT * y$RL_WT - parms$kon_WT * y$R_WT * y$C_W,
dRL_WT = parms$kon_WT * y$R_WT * y$C_WT - parms$koff_WT * y$RL_WT,
dR_WT = parms$koff_WT * y$RL_WT - parms$kon_WT * y$R_WT * y$C_WT ))
}
ode_frame <- function(koff_var){
times <- seq(0, 1, 0.01)
data.frame(ode(y = c(C_WT = 10, RL_WT = 0, R_WT = 20),
times = times, func = Complex,
parms = list(kon_WT = 1, koff_WT = koff_var)))
}
So you could create a list of three data frames for three different values of koff_WT using lapply:
new_koffs <- c(0.5, 1, 1.5)
Output <- lapply(new_koffs, ode_frame)
The result is too large to print here, but this is its structure:
str(Output)
#> List of 3
#> $ :'data.frame': 101 obs. of 4 variables:
#> ..$ time : num [1:101] 0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 ...
#> ..$ C_WT : num [1:101] 10 8.27 6.95 5.91 5.08 ...
#> ..$ RL_WT: num [1:101] 0 1.73 3.05 4.09 4.92 ...
#> ..$ R_WT : num [1:101] 20 18.3 16.9 15.9 15.1 ...
#> $ :'data.frame': 101 obs. of 4 variables:
#> ..$ time : num [1:101] 0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 ...
#> ..$ C_WT : num [1:101] 10 8.27 6.96 5.94 5.13 ...
#> ..$ RL_WT: num [1:101] 0 1.73 3.04 4.06 4.87 ...
#> ..$ R_WT : num [1:101] 20 18.3 17 15.9 15.1 ...
#> $ :'data.frame': 101 obs. of 4 variables:
#> ..$ time : num [1:101] 0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 ...
#> ..$ C_WT : num [1:101] 10 8.27 6.97 5.96 5.17 ...
#> ..$ RL_WT: num [1:101] 0 1.73 3.03 4.04 4.83 ...
#> ..$ R_WT : num [1:101] 20 18.3 17 16 15.2 ...
Related
Edit:
What I want to know in its simplest form:
How do I get the following cumsum data-set with a for-loop:
1 = 1
1+2 = 3
1+2+3 = 6
1+2+3+4= 10
1+2+3+4+5 = 15
When I try this code; I do not get the restult I want
test <- c(0,0,0,0,0)
for (i in 1:5) {test[i] <- sum(i)}
test
[1] 1 2 3 4 5
Actual Problem:
I want to translate the following formula into R:
What I tried is the following, but it gives me wrong values unfortunately:
P <- rnorm(20,100,6)
exp <- function( theta){
for (t in (3:20)){
for (k in (1:(t-1))){
X[t] = (1-theta) * sum( theta^(k-1)*(P[t-k] - P[t-k-1])) + theta^(t-1)}
}
I am sure I am using the sum operator wrong, but I my brain is totally blocked right and I do not know how to properly use it here.
I would appreciate your help.
The convoluted way:
for(i in 1:5){
if(!exists("x")){
print(x <- 1)
} else {
print(x <- x + i)
}
}; rm(i, x)
The simple way:
cumsum(1:5)
You can create your function exp so that it will depend on theta and t and then Vectorize it. Try out:
set.seed(1)
P <- rnorm(20,100,6)
exp <- function(theta, t){
for (k in 1:(t-1)) {
X = (1-theta) * sum(theta^(k-1)*(P[t-k] - P[t-k-1])) + theta^(t-1)
}
return(X)
}
exp <- Vectorize(exp)
exp(0.6, 3:20) # setting theta to 0.6 for instance
# output
[1] 3.600000e-01 2.160000e-01 1.296000e-01
[4] 7.776000e-02 4.665600e-02 2.799360e-02
[7] 1.679616e-02 1.007770e-02 6.046618e-03
[10] 3.627971e-03 2.176782e-03 1.306069e-03
[13] 7.836416e-04 4.701850e-04 2.821110e-04
[16] 1.692666e-04 1.015600e-04 6.093597e-05
You can also use a for loop for different theta values:
my.list <- list()
for (i in seq(0.1, 0.9, 0.1)) {
val = exp(i, 3:20)
my.list[[paste0("theta", i)]] <- val
}
str(my.list)
# my.list
List of 9
$ theta0.1: num [1:18] 1e-02 1e-03 1e-04 1e-05 1e-06 ...
$ theta0.2: num [1:18] 4.0e-02 8.0e-03 1.6e-03 3.2e-04 6.4e-05 ...
$ theta0.3: num [1:18] 0.09 0.027 0.0081 0.00243 0.000729 ...
$ theta0.4: num [1:18] 0.16 0.064 0.0256 0.0102 0.0041 ...
$ theta0.5: num [1:18] 0.25 0.125 0.0625 0.0312 0.0156 ...
$ theta0.6: num [1:18] 0.36 0.216 0.1296 0.0778 0.0467 ...
$ theta0.7: num [1:18] 0.49 0.343 0.24 0.168 0.118 ...
$ theta0.8: num [1:18] 0.64 0.512 0.41 0.328 0.262 ...
$ theta0.9: num [1:18] 0.81 0.729 0.656 0.59 0.531 ...
I have data as follows:
#create sample data frame
df <- data.frame(red_alice_type1 = runif(10, 0, 10),
blue_alice_type1 = runif(10, 0, 10),
green_alice_type1 = runif(10, 0, 10),
red_bob_type1 = runif(10, 0, 10),
blue_bob_type1 = runif(10, 0, 10),
green_bob_type1 = runif(10, 0, 10),
red_alice_type2 = runif(10, 0, 10),
blue_alice_type2 = runif(10, 0, 10),
green_alice_type2 = runif(10, 0, 10),
red_bob_type2 = runif(10, 0, 10),
blue_bob_type2 = runif(10, 0, 10),
green_bob_type2 = runif(10, 0, 10))
I'd like to multiply each color-name pair to create a new column. e.g. blue_alice_type1 * blue_alice_type2 = blue_alice_product
I attempt to iterate over columns to perform this multiplation as follows:
#categories
colors <- c('red', 'blue', 'green')
names <- c('alice', 'bob')
#Attempt 1: Mutate
for (i in colors){
for (j in names){
df <- mutate_(df,
paste(i, j, 'product', sep = "_") = paste(i, j, 'type1', sep = "_") *
paste(i, j, 'type2', sep = "_"))
}
}
#Attempt 2: Base R
for (i in colors){
for (j in names){
assign( paste0('df$', paste(i, j, 'product', sep = "_")),
eval(parse(text=paste0('df$', paste(i, j, 'type1', sep = "_")))) *
eval(parse(text=paste0('df$', paste(i, j, 'type2', sep = "_")))))
}
}
Attempt 1 gives an error. Attempt 2 runs but doesn't create new columns. Any help?
I would split the columns on type and then calculate the product:
#split on type and sort names
type1 <- df[sort(grep('type1', names(df), value = TRUE))]
type2 <- df[sort(grep('type2', names(df), value = TRUE))]
#multiply (both data.frames have the same number of rows and columns)
new_product <- type1 * type2
#change names
names(new_product) <- gsub('type1', 'product', names(new_product))
str(cbind(df, new_product))
#'data.frame': 10 obs. of 18 variables:
# $ red_alice_type1 : num 9.46 4.024 1.953 9.411 0.373 ...
# $ blue_alice_type1 : num 3.34 8.24 4.85 9.46 2.19 ...
# $ green_alice_type1 : num 1.365 5.804 1.23 6.509 0.966 ...
# $ red_bob_type1 : num 0.357 9.931 4.165 1.835 8.526 ...
# $ blue_bob_type1 : num 1.488 1.532 2.848 0.907 0.914 ...
# $ green_bob_type1 : num 8.275 8.482 9.895 0.657 1.457 ...
# $ red_alice_type2 : num 2.188 7.536 4.391 0.202 5.482 ...
# $ blue_alice_type2 : num 4.923 0.593 6.588 5.308 4.671 ...
# $ green_alice_type2 : num 3.76 6.96 2.54 7.53 9.93 ...
# $ red_bob_type2 : num 6.051 9.788 0.369 7.504 1.61 ...
# $ blue_bob_type2 : num 7.55 9.56 1.1 7.89 6.48 ...
# $ green_bob_type2 : num 2.36 2.94 7.57 2.62 6.74 ...
# $ blue_alice_product : num 16.47 4.89 31.94 50.23 10.25 ...
# $ blue_bob_product : num 11.24 14.64 3.14 7.15 5.92 ...
# $ green_alice_product: num 5.13 40.38 3.13 49.05 9.59 ...
# $ green_bob_product : num 19.56 24.94 74.9 1.72 9.82 ...
# $ red_alice_product : num 20.7 30.32 8.58 1.9 2.05 ...
# $ red_bob_product : num 2.16 97.2 1.54 13.77 13.73 ...
I have a list of 100 items.
I want to split it after each 10th item in Code 1.
Code 2 is about a list of two former lists and splitting it to 20 lists of 10 items each.
Code 1
Expected output: ten lists of 10 items.
A <- 100
a <- rnorm(A) # [1:100]
n <- 10
str(a)
# Not resulting in equal size of chunks with vectors so reject
# http://stackoverflow.com/a/3321659/54964
#d <- split(d, ceiling(seq_along(d)/(length(d)/n)))
# Works for vectors but not with lists
# http://stackoverflow.com/a/16275428/54964
#d <- function(d,n) split(d, cut(seq_along(d), n, labels = FALSE))
str(d)
Test code 2
Input: a list of two lists
aa <- list(a, rnorm(a))
Expected output: 20 lists of 10 item size
Testing Loki's answer
segmentLists <- function(A, segmentSize) {
res <- lapply(A, function(x) split(unlist(x), cut(seq_along(unlist(x)), segmentSize, labels = F)))
#print(res)
res <- unlist(res, recursive = F)
}
segmentLists(aa, 10)
Output: loop going on, never stopping
OS: Debian 8.5
R: 3.3.1
you can use lapply.
aa <- list(a, rnorm(a))
aa
n <- 10
x <- lapply(aa, function(x) split(unlist(x), cut(seq_along(unlist(x)), n, labels = F)))
y <- unlist(x, recursive = F)
str(y)
# List of 20
# $ 1 : num [1:10] 1.0895 -0.0477 0.225 -0.6308 -0.1558 ...
# $ 2 : num [1:10] -0.469 -0.381 0.709 -0.798 1.183 ...
# $ 3 : num [1:10] 0.757 -1.128 -1.394 -0.712 0.494 ...
# $ 4 : num [1:10] 1.135 0.324 0.75 -0.83 0.794 ...
# $ 5 : num [1:10] -0.786 -0.068 -0.179 0.354 -0.597 ...
# $ 6 : num [1:10] -0.115 0.164 -0.365 -1.827 -2.036 ...
...
length(y)
# [1] 20
to remove the names of the list elements in y ($ 1, $ 2 etc.) you can use unname()
str(unname(y))
# List of 20
# $ : num [1:10] 1.0895 -0.0477 0.225 -0.6308 -0.1558 ...
# $ : num [1:10] -0.469 -0.381 0.709 -0.798 1.183 ...
# $ : num [1:10] 0.757 -1.128 -1.394 -0.712 0.494 ...
# $ : num [1:10] 1.135 0.324 0.75 -0.83 0.794 ...
# $ : num [1:10] -0.786 -0.068 -0.179 0.354 -0.597 ...
...
Using a function, you have to return res at the end of the function.
segmentLists <- function(A, segmentSize)
{
res <- lapply(A, function(x) split(unlist(x), cut(seq_along(unlist(x)), segmentSize, labels = F)))
#print(res)
res <- unlist(res, recursive = F)
res <- unname(res)
res
}
Here is my dataframe example. It includes a column variable, named "dta" which is a single list of n values I want to keep for each of my scenario:
set.seed(777)
df <- data.frame(theo = numeric(),
size = numeric(),
dta = I(list()))
df[ 1: 5,"theo"] <- qlnorm(0.1, meanlog=0, sdlog=1, lower.tail = TRUE, log.p = FALSE)
df[ 6:10,"theo"] <- qlnorm(0.2, meanlog=0, sdlog=1, lower.tail = TRUE, log.p = FALSE)
df[ 1: 5,"size"] <- 10
df[ 6:10,"size"] <- 20
for(i in 1:10){
df$dta[i] <- list(rlnorm(df$size[i], meanlog = 0, sdlog = 1))
}
df
str(df)
This should give a df like:
theo size dta
1 0.2776062 10 1.631967....
2 0.2776062 10 0.737667....
3 0.2776062 10 0.131252....
4 0.2776062 10 1.937334....
5 0.2776062 10 0.739868....
6 0.4310112 20 4.631176....
7 0.4310112 20 2.610180....
8 0.4310112 20 0.175918....
9 0.4310112 20 3.501670....
10 0.4310112 20 0.588178....
or:
'data.frame': 10 obs. of 4 variables:
$ theo: num 0.278 0.278 0.278 0.278 0.278 ...
$ size: num 10 10 10 10 10 20 20 20 20 20
$ dta :List of 10
..$ : num 1.632 0.671 1.667 0.671 5.148 ...
..$ : num 0.738 1.056 0.152 0.967 10.089 ...
..$ : num 0.131 1.256 0.457 3.574 4.211 ...
..$ : num 1.937 2.359 3.496 0.297 4.587 ...
..$ : num 0.74 0.66 0.481 0.434 1.874 ...
..$ : num 4.631 0.298 10.28 0.933 1.286 ...
..$ : num 2.61 0.472 0.251 1.61 0.303 ...
..$ : num 0.176 0.566 2.156 0.407 3.52 ...
..$ : num 3.502 1.748 1.283 0.648 1.359 ...
..$ : num 0.588 0.392 2.447 1.926 0.86 ...
..- attr(*, "class")= chr "AsIs"
Now, I want to subset that list in such a way that:
for each list, each value is compared with the fixed value "theo" stored in the dataframe
when that value is below or equal to "theo", then recode that value NA
Here is a working code and gives me exactly what I want:
df$dta2 <- df$dta
for(i in 1:10){
df$dta2[[i]] [ df$dta2[[i]] <= df$theo[i] ] <- NA
}
However I was wondering is there is a way to get the same result with a single line of code and no "for loop" to proceed with a conditional replacement of values contained in a list which is nested in a dataframe?
We can use Map
df$dta3 <- Map(function(x,y) replace(x, x<=y, NA), df$dta, df$theo)
all.equal(df$dta2, df$dta3, check.attributes=FALSE)
#[1] TRUE
I have a function which contains a loop over two lists and builds up some calculated data. I would like to return these data as a lists of lists, indexed by some value, but I'm getting the assignment wrong.
A minimal example of what I'm trying to do, and where i'm going wrong would be:
mybiglist <- list()
for(i in 1:5){
a <- runif(10)
b <- rnorm(16)
c <- rbinom(8, 5, i/10)
name <- paste('item:',i,sep='')
tmp <- list(uniform=a, normal=b, binomial=c)
mybiglist[[name]] <- append(mybiglist, tmp)
}
If you run this and look at the output mybiglist, you will see that something is going very wrong in the way each item is being named.
Any ideas on how I might achieve what I actually want?
Thanks
ps. I know that in R there is a sense in which one has failed if one has to resort to loops, but in this case I do feel justified ;-)
It works if you don't use the append command:
mybiglist <- list()
for(i in 1:5){
a <- runif(10)
b <- rnorm(16)
c <- rbinom(8, 5, i/10)
name <- paste('item:',i,sep='')
tmp <- list(uniform=a, normal=b, binomial=c)
mybiglist[[name]] <- tmp
}
# List of 5
# $ item:1:List of 3
# ..$ uniform : num [1:10] 0.737 0.987 0.577 0.814 0.452 ...
# ..$ normal : num [1:16] -0.403 -0.104 2.147 0.32 1.713 ...
# ..$ binomial: num [1:8] 0 0 0 0 1 0 0 1
# $ item:2:List of 3
# ..$ uniform : num [1:10] 0.61 0.62 0.49 0.217 0.862 ...
# ..$ normal : num [1:16] 0.945 -0.154 -0.5 -0.729 -0.547 ...
# ..$ binomial: num [1:8] 1 2 2 0 2 1 0 2
# $ item:3:List of 3
# ..$ uniform : num [1:10] 0.66 0.094 0.432 0.634 0.949 ...
# ..$ normal : num [1:16] -0.607 0.274 -1.455 0.828 -0.73 ...
# ..$ binomial: num [1:8] 2 2 3 1 1 1 2 0
# $ item:4:List of 3
# ..$ uniform : num [1:10] 0.455 0.442 0.149 0.745 0.24 ...
# ..$ normal : num [1:16] 0.0994 -0.5332 -0.8131 -1.1847 -0.8032 ...
# ..$ binomial: num [1:8] 2 3 1 1 2 2 2 1
# $ item:5:List of 3
# ..$ uniform : num [1:10] 0.816 0.279 0.583 0.179 0.321 ...
# ..$ normal : num [1:16] -0.036 1.137 0.178 0.29 1.266 ...
# ..$ binomial: num [1:8] 3 4 3 4 4 2 2 3
Change
mybiglist[[name]] <- append(mybiglist, tmp)
to
mybiglist[[name]] <- tmp
To show that an explicit for loop is not required
unif_norm <- replicate(5, list(uniform = runif(10),
normal = rnorm(16)), simplify=F)
binomials <- lapply(seq_len(5)/10, function(prob) {
list(binomial = rbinom(n = 5 ,size = 8, prob = prob))})
biglist <- setNames(mapply(c, unif_norm, binomials, SIMPLIFY = F),
paste0('item:',seq_along(unif_norm)))
In general if you go down the for loop path it is better to preassign the list beforehand. This is more memory efficient.
mybiglist <- vector('list', 5)
names(mybiglist) <- paste0('item:', seq_along(mybiglist))
for(i in seq_along(mybiglist)){
a <- runif(10)
b <- rnorm(16)
c <- rbinom(8, 5, i/10)
tmp <- list(uniform=a, normal=b, binomial=c)
mybiglist[[i]] <- tmp
}