Limit the values used in a function to their sum - r

I created a function with that I want to calculate (several) vectors of data.
Actually the vctors should be for a range (1:100) for one variable while the others stay constant at differnt values in turn.
The function is:EI <- function(x,y,z) {(x+y)/(2*(2*x+y)+z)}
my Problem is, the sum of x+y+z has to be limited to 100. And i don't know how to tell it the function.
For example, if x = 20, y can only take values from 0:80 , i.e. (100-20), and z can takey values from 0 : 100-(x+y).
I used the following code where z is not regarded all. I thought, I would get at least one large vector, but all I get is a single number:
for(x in 1:100) {
for(y in 0:(100-x)) {
for(z in 0:(100-(x+y))) {
v1 <- c(EI(x,y,z))
}
}
}
I need to tell the function EI() that the sum of x+y+z has alwys to be 100.
Has anybody an idea how to solve this problem?

If you want to create a vector you need to do that:
v1 <- c()
for(x in 1:100) {
for(y in 0:(100-x)) {
for(z in 0:(100-(x+y))) {
v1 <- c(v1, EI(x,y,z))
}
}
}
Unfortunately this will be slow (because at each step you are reallocating a new vector), a better alternative is to begin by allocate your vector with the appropriate size:
v1 <- numeric(171700)
k <- 0
for(x in 1:100) {
for(y in 0:(100-x)) {
for(z in 0:(100-(x+y))) {
k <- k + 1
v1[k] <- EI(x,y,z)
}
}
}
You can also write the same thing with sapply function and this is slightly faster:
v1 <- unlist(sapply(1:100,
function(x) {
unlist(sapply(0:(100-x),
function(y) {
sapply(0:(100-(x+y)),
function(z) {EI(x,y,z)}) }))}))

Related

why my sum() function don't work for the matrix operations in R

The following is my R code, I want the tx[1, 1] = 1*2^1 + 4*5^2 + 7*8^3, tx[1, 2] = 4*5 + 7*8^2, tx[1, 3] = 7*8,but it only including 7*8^3 for tx[1, 1] and 7*8^2 for tx[1, 2]. The other elements in the tx matrix only include the last term in the sum operation too. So,could anyone tell me how to rectify my code to have a correct output? Thanks in advance!
A <- matrix(c(1:9),ncol=3)
B <- matrix(c(2:10),ncol=3)
tx<-matrix(rep(NA,3*3),3,3)
for(j in 1:3)
{
for(i in 1:3)
{
for(k in 1:3-i+1)
{
tx[j,i]<-sum(A[j,k+i-1]*(B[j,k+i-1])^k)
}
}
}
Right now it's not summing the results of each loop, just saving out whatever the last loop result happens to be. Try this instead:
A <- matrix(c(1:9),ncol=3)
B <- matrix(c(2:10),ncol=3)
tx<-matrix(rep(0,3*3),3,3)
for(j in 1:3)
{
for(i in 1:3)
{
for(k in 1:3-i+1)
{
tx[j,i]<-tx[j,i] + (A[j,k+i-1]*(B[j,k+i-1])^k)
}
}
}
I initialized the tx matrix to start at 0 and added the result of each loop to the existing total, so that it increments over each loop.

How to fill in matrix inside of foreach loop?

I would like to fill in the matrix in inside of the parallel loop.
When I call the function, it returns back me the empty matrix
I was wondering whether can someone help me with that.
Compute_TaskSimilarity<-function(X,...){
Task_similarity<-matrix(0,nrow=100,ncol=100)
foreach(i = 1:K, .combine = "cbind") %dopar% {
for (j in (i + 1):(ncol(Task_similarity))) {
Myvalue<- ComputeValue
if (Myvalue!=0){
TaskSimilarity[i, j] <- Myvalue
} else{
TaskSimilarity[i, j] <- 0.0
}
}
return(TaskSimilarity)
}
Maybe do something like this: create a data.frame of all combinations of indices, then apply over all combinations, then reshape into a matrix of the right size. (I added a simple multiplication as example for a more complex operation and used a smaller array of lenght 10):
indices <- data.frame(x=rep(1:10, each=10), y=rep(1:10, 10))
result <- foreach(i=1:nrow(indices)) %dopar% {
# just an example for a more complex calculation
indices$x[i] * indices$y[i]
}
result <- do.call(c, result)
dim(result) <- c(10, 10)

For loop function with two subscripts

I am new to writing loop functions and I am trying to solve this. I would like the y matrix to be populated with the values obtained from the for loop. Unfortunately y remains blank and full of 0's after the loop is executed.
mv <- c(0,1,2) # location vector
s <- 1 # scale
increment <- seq(-6,6,0.01) # Create a sequence of x values
y=matrix(0,length(increment),length(mv))
for (i in length(increment)) {
for (j in length(mv)) {
y[i,j] <- 1/(1+ exp(-(increment[i]-mv[j])/s))
}
}
Change your loop to start at 1, for now it is only using 1 value (length(increment)):
for (i in 1:length(increment)) {
for (j in 1:length(mv)) {
y[i,j] <- 1/(1+ exp(-(increment[i]-mv[j])/s))
}
}

Using If trying to get a vector a certain length

I'm trying to use if function to create a vector X that follows the pattern of the if statement, that is length 5. However, when I print X, I get 5 vectors with length 1. How do I fix this
for (i in 1:5) {
if (i <2){
a<-i
}
else {
a<-(i-1)
}
X<-a
print(X)
}
R overwrites the contents of your variables a and X with each loop. To avoid this, you can make X a list, and put your value in a different position with each loop.
X <- list()
a <- list()
for(i in 1:5) {
if(i<2){
a <- i
} else {
a <- i-1
}
X[i] <- a
}
Since your final plan is to create a vector, you may initialize a vector ("X") first, and then add a value ("a") in each 'for' loop.
X = vector("numeric",0)
for (i in 1:5){
if (i<2){
a <- i
}
else{
a <- (i-1)
}
X = c(X, a)
print(X)
}
X
# [1] 1 1 2 3 4

specify dynamic array indexes programmatically

I'd like to generalize this code to handle an array of any number of dimensions but I'm not sure how to specify array indexes programatically. I think its possible with some combination of paste eval substitute quote but I can't figure it out.
x <- array(runif(1000),dim=c(10,10,10))
w <- vector("list")
for (i in seq(dim(x)[1]))
{
w[i] <- list(which(x[i,,] == max(x[i,,]),arr.ind=TRUE))
}
for (i in seq(dim(x)[1]))
{
# looking for something like:
# s <- paste(i,",",paste(w[[i]],collapse=","),sep="")
# v <- x[s]
v <- x[i,w[[i]][[1]],w[[i]][[2]]]
print(paste("the max at index",i,"is",round(v,4)),quote=FALSE)
}
nvm, figured out how to do it
x <- array(runif(1000),dim=c(10,10,10))
w <- vector("list")
for (i in seq(dim(x)[1]))
{
w[i] <- list(which(x[i,,] == max(x[i,,]),arr.ind=TRUE))
}
for (i in seq(dim(x)[1]))
{
v <- do.call(`[`,c(list(x,i),w[[i]]))
print(paste("the max at index",i,"is",round(v,4)),quote=FALSE)
}

Resources