How to make nested for-loop do every permutation - r

Basic question, but unsure how to resolve based on other posts that use vectors of characters or other situations that don't fully enlighten my own simple problem.
I want to make a nested for loop to calculate all possible combinations of two equations (x and y) along two vectors, and store every single calculation.
Here is my code:
n_c = 1
m_c = 1
n_n = 1
m_n = 1
my_data_c = c()
my_data_n = c()
rho_c_store = c()
rho_n_store = c()
for(i in 1:10){
for(j in 1:10){
rho_c = i / 10
rho_n = j / 10
x = (rho_c*n_c)/m_c
y = (rho_n*n_n)/m_n
rho_c_store[i] = rho_c
rho_n_store[j] = rho_n
my_data_c[i] = x
my_data_n[j] = y
my_data = cbind(rho_c_store,rho_n_store,my_data_c,my_data_n)
}
}
print(my_data)
The output I get is:
> print(my_data)
rho_c_store rho_n_store my_data_c my_data_n
[1,] 0.1 0.1 0.1 0.1
[2,] 0.2 0.2 0.2 0.2
[3,] 0.3 0.3 0.3 0.3
[4,] 0.4 0.4 0.4 0.4
[5,] 0.5 0.5 0.5 0.5
[6,] 0.6 0.6 0.6 0.6
[7,] 0.7 0.7 0.7 0.7
[8,] 0.8 0.8 0.8 0.8
[9,] 0.9 0.9 0.9 0.9
[10,] 1.0 1.0 1.0 1.0
However, the data I want is:
> print(my_data)
rho_c_store rho_n_store my_data_c my_data_n
[1,] 0.1 0.1 ? ?
[2,] 0.1 0.2 ? ?
[3,] 0.1 0.3 ? ?
[4,] 0.1 0.4 ? ?
[5,] 0.1 0.5 ? ?
[6,] 0.1 0.6 ? ?
[7,] 0.1 0.7 ? ?
[8,] 0.1 0.8 ? ?
[9,] 0.1 0.9 ? ?
[10,] 0.1 1.0 ? ?
[11,] 0.2 0.1 ? ?
[12,] 0.2 0.2 ? ?
[13,] 0.2 0.3 ? ?
[14,] 0.2 0.4 ? ?
[15,] 0.2 0.5 ? ?
... etc
I know I could solve this in some way with grid.expand() and an apply() function (trying to figure that out in parallel), but I'm annoyed at my inability to solve this basic code setup.
Thanks!

As the others have pointed out you overwrite your elements again and again - you do not actually assign to the row that you mean to. I've included the code that explicitly calculates the index - maybe this is clearer to you. I've also made a few corrections (e.g. you can take the final construction out of the loop).
n_c <- 1 # generally: use <- for assignment
m_c <- 1
n_n <- 1
m_n <- 1
my_data_c <- c() # better: pre-allocate as vector("numeric", 100)
my_data_n <- c()
rho_c_store <- c()
rho_n_store <- c()
for (i in 1:10) {
# you can move this assignment to the outer loop
rho_c <- i / 10
x <- (rho_c * n_c)/m_c
for (j in 1:10) {
rho_n <- j / 10
y <- (rho_n * n_n)/m_n
index <- 10*(i-1) + j
rho_c_store[index] <- rho_c
rho_n_store[index] <- rho_n
my_data_c[index] <- x
my_data_n[index] <- y
}
}
# cbind should be outside the for loop, you only want to build the final
# matrix once you've completed building the vectors
my_data <- cbind(rho_c_store, rho_n_store, my_data_c, my_data_n)
print(my_data)
Hope this helps

The problem is, that you store the variables at the wrong place. In other words when you loop through the second for-loop your i has always the same value. So you store each result of x on the same place. That's why you have to create an index which goes from 1:100 (in your case), and not from 1:10 only.
Hope you understand what I mean.
If I take your code with with some corrections it should look like this
n_c = 1
m_c = 1
n_n = 1
m_n = 1
my_data_c = c()
my_data_n = c()
rho_c_store = c()
rho_n_store = c()
iter = 10
for(i in 1:iter){
sequence = seq(i*iter-iter+1,i*iter)
for(j in 1:iter){
index = sequence[j]
rho_c = i / 10
rho_n = j / 10
x = (rho_c*n_c)/m_c
y = (rho_n*n_n)/m_n
rho_c_store[index] = rho_c
rho_n_store[index] = rho_n
my_data_c[index] = x
my_data_n[index] = y
my_data = cbind(rho_c_store,rho_n_store,my_data_c,my_data_n)
}
}
print(my_data)
In my example my seqence is an altering index which goes from 1 to 10 when i = 1 and then from 11 to 20 and so on.
I hope this is what you meant.

Related

Create fully antithetic draws using R

say I have the matrix d, which is the result of two different realizations (rows) of a sampling procedure in two dimensions (columns). I want to develop a function that creates the fully-antithetic draws from this original matrix.
c1 <- c(0.1, 0.6);c2 <- c(0.3, 0.8);d <- rbind(c1,c2)
# [,1] [,2]
# c1 0.1 0.6
# c2 0.3 0.8
That is to say, for example, for the first realization (c(0.1, 0.6)) I want to obtain the mirror images of this random draw in two dimensions, which generated 4 (2^2) possible combinations as follows:
d1_anthi = matrix(
c( d[1,1] , d[1,2],
1 - d[1,1], d[1,2],
d[1,1] , 1 - d[1,2],
1 - d[1,1], 1 - d[1,2]), nrow=2,ncol=4)
t(d1_anthi)
# [,1] [,2]
# [1,] 0.1 0.6
# [2,] 0.9 0.6
# [3,] 0.1 0.4
# [4,] 0.9 0.4
Analogously, for the second, realization the results is the following:
d2_anthi = matrix(
c( d[2,1] , d[2,2],
1 - d[2,1], d[2,2],
d[2,1] , 1 - d[2,2],
1 - d[2,1], 1 - d[2,2]), nrow=2, ncol=4)
t(d2_anthi)
# [,1] [,2]
# [1,] 0.3 0.8
# [2,] 0.7 0.8
# [3,] 0.3 0.2
# [4,] 0.7 0.2
Accordingly, my desired object will lock is like this:
anthi_draws <- rbind(t(d1_anthi),t(d2_anthi))
# [,1] [,2]
# [1,] 0.1 0.6 <- original first realization
# [2,] 0.9 0.6
# [3,] 0.1 0.4
# [4,] 0.9 0.4
# [5,] 0.3 0.8 <- original second realization
# [6,] 0.7 0.8
# [7,] 0.3 0.2
# [8,] 0.7 0.2
Finally, I would like to create a function that, given a matrix of random numbers, is able to create this expanded matrix of antithetic draws. For example, in the picture below I have a sampling in three dimensions, then the total number of draws per original draw is 2^3 = 8.
In particular, I am having problems with the creating of the full combinatory that depends on the dimensions of the original sampling (columns of the matrix). I was planning on using expand.grid() but I couldn't create the full combinations using it. Any hints or help in order to create such a function is welcome. Thank you in advance.
You can try this
do.call(
rbind,
apply(
d,
1,
function(x) {
expand.grid(data.frame(rbind(x, 1 - x)))
}
)
)
which gives
X1 X2
c1.1 0.1 0.6
c1.2 0.9 0.6
c1.3 0.1 0.4
c1.4 0.9 0.4
c2.1 0.3 0.8
c2.2 0.7 0.8
c2.3 0.3 0.2
c2.4 0.7 0.2

How to solve this R error: In thdim[i] <- `*vtmp*` : number of items to replace is not a multiple of replacement length

I encountered the warning in the title when I ran the following code and the results also look weird:
thdim <- matrix(0,nrow=5,ncol=4)
d <- c(1, 2, 2, 1)
theta <- matrix(c(1,0.5,0.75,0.83,0.91,0.1,0.4,1.2,0.6,0.2),ncol=2)
thetanew <- matrix(0,nrow=5,ncol=2)
thetanew<- cbind(theta, thetanew)
for (i in 1:5) {
for (j in 1:4) {
thdim[i][j] <- thetanew[i][d[j]]
}
}
Can anyone help me with this error? Thanks!
We can use d as an index to subset columns from theta.
thdim <- matrix(0,nrow=5,ncol=4)
d <- c(1, 2, 2, 1)
theta <- matrix(c(1,0.5,0.75,0.83,0.91,0.1,0.4,1.2,0.6,0.2),ncol=2)
theta[, d]
# [,1] [,2] [,3] [,4]
#[1,] 1.00 0.1 0.1 1.00
#[2,] 0.50 0.4 0.4 0.50
#[3,] 0.75 1.2 1.2 0.75
#[4,] 0.83 0.6 0.6 0.83
#[5,] 0.91 0.2 0.2 0.91
To correct the for loop, we can do :
for (i in 1:5) {
#You can use nrow(thdim) instead of hard coding 5
for (j in 1:4) {
# You can use `length(d)` instead of hardcoding 4
thdim[i, j] <- theta[i, d[j]]
}
}

use function code to produce a n×n matrix

In order to produce the matrix in the picture, I tried to write a function code to do this, but I cannot figure it out what to do next, and also not sure if what I already did is right or not.
Matrix <- function(n){
mat1 <- diag(x = ((1:n)-1)/((1:n)+1), n, n)[-1,]
mat2 <- diag(x = ((1:n)-(1:n)+1)/((1:n)+1), n, n)[,-1]
mat3 <- diag(x = 1/((1:n)+1), n, n)
}
An option:
library(SoDA)
n <- 4
triDiag(diagonal = rep(1/(n+1), n+1),
upper = (n:1)/(n+1),
lower = (1:n)/(n+1))
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.2 0.8 0.0 0.0 0.0
# [2,] 0.2 0.2 0.6 0.0 0.0
# [3,] 0.0 0.4 0.2 0.4 0.0
# [4,] 0.0 0.0 0.6 0.2 0.2
# [5,] 0.0 0.0 0.0 0.8 0.2
It is not entirely clear what you are trying to achieve.
From your description the matrix will have n+1 elements (from 1/(n+1) to n/(n+1)), and I assume the remaining matrix is Sparse. It is not a simple structure to achieve via vectorized computations, but it can be achieved in a single for loop, thus being constructed in O(n) time, given a matrix of size n+1.
In the code below i present an example of such code. The idea is to traverse the matrix in opposite, and only assign 1 type value to each.
Create_Matrix <- function(n){
n1 = n + 1 #Last row, avoid n computations
n2 = n1 + 1
output <- diag(1/n1, nrow = n1, ncol = n1)
for(i in seq(n)){
output[i + 1, i] = output[n1 - i, n2 - i] = output[[1]] * i
}
output
}

Combinations of values in each cell in a symmetric matrix

I have a vector of weights that I want to insert in a symmetric matrix. I want all combinations of weights (all weights in all positions but not in the diagonal)
I tried iterating through the matrix, but then I only get the same matrix triplicate. (Also I couldn't find it answered or a public solution to this problem.)
weight <- seq(0.1, 1, by = 0.1)
C <- matrix(0, nrow = 3, ncol = 3)
for (i in seq_len(nrow(C))) {
C_old <- C
for (j in seq_len(i)) {
if (i == j) {
C[i, i] <- 0
} else {
C_old2 <- C_old
for (w in weight) {
C[i, j] <- w
C[j, i] <- C[i, j]
C_old[i, j] <- w
C_old[j, i] <- C_old[i, j]
C_old2[i, j] <- w
C_old2[j, i] <- C_old2[i, j]
iter <- iter + 3
print(C)
print(C_old)
print(C_old2)
}
}
}
I want to have all the matrices such that
Matrix 0:
0 0 0
0 0 0
0 0 0
Matrix 1:
0 0 0
0 0 0.1
0 0.1 0
Matrix 2:
0 0 0.1
0 0 0.1
0.1 0.1 0
Matrix 3:
0 0.1 0.1
0.1 0 0.1
0.1 0.1 0
Matrix 4:
0 0.1 0.1
0.1 0 0.2
0.1 0.2 0
Matrix n:
0 0.9 0.1
0.5 0 0.5
0.1 0.9 0
Matrix:
0 x y
z 0 z
y x 0
I want all combinations of the last matrix were x, y and z can be any value in weight.
The first matrix (all 0) is not really important, so if a solution omits it I don't really care
No idea what you want this for, but here you go:
weight <- seq(0.1, 1, by = 0.1)
C <- matrix(0, nrow = 3, ncol = 3)
C_list <- vector("list", 10)
for(i in 1:length(weight)){
for(j in 1:3){
if(j == 1){
C[2,3] <- weight[i]
C[3,2] <- weight[i]
}
if(j == 2){
C[1,3] <- weight[i]
C[3,1] <- weight[i]
}
if(j == 3){
C[1,2] <- weight[i]
C[2,1] <- weight[i]
}
C_list[[i]][[j]] <- C
}
}
Result:
> C_list
[[1]]
[[1]][[1]]
[,1] [,2] [,3]
[1,] 0 0.0 0.0
[2,] 0 0.0 0.1
[3,] 0 0.1 0.0
[[1]][[2]]
[,1] [,2] [,3]
[1,] 0.0 0.0 0.1
[2,] 0.0 0.0 0.1
[3,] 0.1 0.1 0.0
[[1]][[3]]
[,1] [,2] [,3]
[1,] 0.0 0.1 0.1
[2,] 0.1 0.0 0.1
[3,] 0.1 0.1 0.0
[[2]]
[[2]][[1]]
[,1] [,2] [,3]
[1,] 0.0 0.1 0.1
[2,] 0.1 0.0 0.2
[3,] 0.1 0.2 0.0
[[2]][[2]]
[,1] [,2] [,3]
[1,] 0.0 0.1 0.2
[2,] 0.1 0.0 0.2
[3,] 0.2 0.2 0.0
...
Thanks to LAP I changed the approach and I managed how to do this:
weight <- seq(0.1, 1, by = 0.1)
C <- matrix(0, nrow = 3, ncol = 3)
C_list <- vector("list", 10)
names(C_list) <- as.character(weight)
for(i1 in weight){
C_list[[as.character(i1)]] <- vector("list", 10)
names(C_list[[as.character(i1)]]) <- as.character(weight)
for (i2 in weight){
C_list[[as.character(i1)]][[as.character(i2)]] <- vector("list", 10)
names(C_list[[as.character(i1)]][[as.character(i2)]]) <- as.character(weight)
for (i3 in weight) {
C[2, 3] <- i1
C[3, 2] <- i1
C[1, 3] <- i2
C[3, 1] <- i2
C[1, 2] <- i3
C[2, 1] <- i3
C_list[[as.character(i1)]][[as.character(i2)]][[as.character(i3)]] <- C
}
}
}
Now the C_list is a list of lists of lists that each one has a matrix. length(unlist(unlist(C_list, recursive = FALSE), recursive = FALSE)) == 1000 that are the 10^3 combinations that exists.

Generate combinations of values which sum to one, sorted in descending order

Do you know a more efficient way to generate a matrix holding all unique combinations of "weights" (let weights be w and 0 <= w <= 1, and values of w are separated by steps of 0.1), such that the weights sum to one AND the first is the highest, the last the lowest weight.
Here is code that does the job, but it seems inefficient to delete rows:
# generate combinations of weights such that w1 >= w2 >= w3 ...
w = seq(0, 1, 0.1) #weights 0, 0.1, ..., 0.9, 1
w = expand.grid(w, w, w, KEEP.OUT.ATTRS = FALSE) #all combinations of 3 weights
w = w[rowSums(w) == 1, ] #make sure the weights sum to one
w = w[!(w[, 1] < w[, 2] | w[, 2] < w[, 3]),] #make sure w1 >= w2 >= w3 ...
w
# Var1 Var2 Var3
# 11 1.0 0.0 0.0
# 21 0.9 0.1 0.0
# 31 0.8 0.2 0.0
# 41 0.7 0.3 0.0
# 51 0.6 0.4 0.0
# 61 0.5 0.5 0.0
# 141 0.8 0.1 0.1
# 151 0.7 0.2 0.1
# 171 0.5 0.4 0.1
# 271 0.6 0.2 0.2
# 281 0.5 0.3 0.2
# 291 0.4 0.4 0.2
# 401 0.4 0.3 0.3
Let me add some more general info:
In this problem (3 weights in the above order) the upper limits for the first, second, third values are as follows:
the first number can minimally be 1 for the combination (1, 0, 0)
the second number can maximally be 1/2 for the combination (1/2, 1/2, 0)
the third number can maximally be 1/3 for the combination (1/3, 1/3, 1/3)
A non-base possibility:
library(partitions)
step <- 0.1
n_weights <- 3
t(restrictedparts(n = 1/step, m = n_weights) * step)
# [1,] 1.0 0.0 0.0
# [2,] 0.9 0.1 0.0
# [3,] 0.8 0.2 0.0
# [4,] 0.7 0.3 0.0
# [5,] 0.6 0.4 0.0
# [6,] 0.5 0.5 0.0
# [7,] 0.8 0.1 0.1
# [8,] 0.7 0.2 0.1
# [9,] 0.6 0.3 0.1
# [10,] 0.5 0.4 0.1
# [11,] 0.6 0.2 0.2
# [12,] 0.5 0.3 0.2
# [13,] 0.4 0.4 0.2
# [14,] 0.4 0.3 0.3
General purpose function with standard packages:
# Generate weights matrix with noWeights columns and noRows rows.
# Each row of this matrix contains sorted decremental weights summing up to 1.0.
generateWeights = function(noWeights,
noRows,
distribution = runif,
rounding = function(x){ round(x, 1) })
{
generator = function()
{
x = distribution (noWeights);
x = x/sum(x);
sort(rounding(x), decreasing = T)
}
t(replicate(noRows, generator()))
}
# example of use
generateWeights(3, 10)

Resources