Translating a formula into R with summation operator - r

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 ...

Related

how to partition the data with specific row size

Say I have the following matrix:
X = matrix(rnorm(4000), nrow=400, ncol=10)
size = c(80,80,79,80,81)
I want to partition the matrix row-wise according to the above size in a concise way. To illustrate,
x1 = X[1:80,]
x2 = X[81:160,]
.
.
x5 = X[320:400,]
I usually have different sizes and different matrices, so I won't be able to do this manually every time. Your help is very much appreciated.
Try the code below
e <- cumsum(size)
b <- c(1, head(e + 1, -1))
out <- Map(function(rb, re) X[rb:re, ], b, e)
and you will see
> str(out)
List of 5
$ : num [1:80, 1:10] 0.253 -0.368 0.804 -0.603 -0.119 ...
$ : num [1:80, 1:10] 0.467 -0.743 -0.401 1.48 0.853 ...
$ : num [1:79, 1:10] -1.123 -0.873 -1.039 -0.247 -0.774 ...
$ : num [1:80, 1:10] -1.409 -0.683 -0.514 0.485 -0.347 ...
$ : num [1:81, 1:10] 0.58 0.529 -0.803 0.49 -0.847 ...
Furthermore, if you want to create variables, try
list2env(setNames(out,paste0("x",seq_along(out))),envir = .GlobalEnv)
You can get start and end points using cumsum and use Map to subset them and create list of matrices.
X = matrix(rnorm(4000), nrow=400, ncol=10)
size = c(80,80,79,80,81)
val <- cumsum(size)
result <- Map(function(x, y) X[x:y, ], c(1, val[-length(val)] + 1), val)
where c(1, val[-length(val)] + 1) creates the starting row numbers and val are the ending ones.
c(1, val[-length(val)] + 1)
#[1] 1 81 161 240 320
val
#[1] 80 160 239 319 400
Using map2
library(purrr)
size1 <- cumsum(size)
map2(size1, c(1, size1[-length(size1)] + 1), ~ X[.x:.y,])

Simulations for different parameter values

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 ...

How to split list at every 10th item in R?

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
}

apply create columns function to a list r

I am new in using apply and functions together and I am stuck and frustrated. I have 2 different list of data frames that I need to add certain number of columns to the first one when a condition is fulfill related to the second one. Below this is the structure of the first list that has one data frame for any station and every df has 2 or more columns with each pressure:
> str(KDzlambdaEG)
List of 3
$ 176:'data.frame': 301 obs. of 3 variables:
..$ 0 : num [1:301] 0.186 0.182 0.18 0.181 0.177 ...
..$ 5 : num [1:301] 0.127 0.127 0.127 0.127 0.127 ...
..$ 20: num [1:301] 0.245 0.241 0.239 0.236 0.236 ...
$ 177:'data.frame': 301 obs. of 2 variables:
..$ 0 : num [1:301] 0.132 0.132 0.132 0.13 0.13 ...
..$ 25: num [1:301] 0.09 0.092 0.0902 0.0896 0.0896 ...
$ 199:'data.frame': 301 obs. of 2 variables:
..$ 0 : num [1:301] 0.181 0.182 0.181 0.182 0.179 ...
..$ 10: num [1:301] 0.186 0.186 0.185 0.183 0.184 ...
On the other hand I have the second list that have the number of columns that I need to add after every column on each data frame of the first list :
> str(dif)
List of 3
[[176]]
[1] 4 15 28
[[177]]
[1] 24 67
[[199]]
[1] 9 53
I´ve tried tonnes of things even this, using the append_col function that appear in:
How to add a new column between other dataframe columns?
for (i in 1:length(dif)){
A<-lapply(KDzlambdaEG,append_col,rep(list(NA),dif[[i]][1]),after=1)
}
but nothing seems to work so far... I have searched for answers here but its difficult to find specific ones being a newcomer.
Try:
indxlst <- lapply(dif, function(x) c(1, x[-length(x)]+1, x[length(x)]))
newdflist <- lapply(indxlst, function(x) data.frame(matrix(0, 2, sum(x))))
for(i in 1:length(newdflist)) {
newdflist[[i]][indxlst[[i]]] <- KDzlambdaEG[[i]]
}
Reproducible Data Test
df1 <- data.frame(x=1:2, y=c("Jan", "Feb"), z=c("A", "B"))
df3 <- df2 <- df1[,-3]
KDzlambdaEG <- list(df1,df2,df3)
x1 <- c(4,15,28)
x2 <- c(24,67)
x3 <- c(9, 53)
dif <- list(x1,x2,x3)
indxlst <- lapply(dif, function(x) c(1, x[-length(x)]+1, x[length(x)]))
newdflist <- lapply(indxlst, function(x) data.frame(matrix(0, 2, sum(x))))
for(i in 1:length(newdflist)) {
newdflist[[i]][indxlst[[i]]] <- KDzlambdaEG[[i]]
}
newdflist

Building a list in a loop in R - getting item names correct

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
}

Resources