R: outer on array in first dimension - arrays

outer in R gives outer product of arrays. For example, for matrix A with dimension c(2, 3),
A <- matrix(1:6, 2, 3)
B <- outer(A, A, function(x,y) x + y)
B has dimension c(2, 3, 2, 3). But can I define a function myouter in a concise way to apply outer only in the first dimension, to get a matrix C?
C <- myouter(A, A, function(x,y) sum(x) + sum(y))
C can be obtained by the following tedious code.
C <- matrix(nrow = 2, ncol = 2)
for (i in 1:2) {
for (j in 1:2) {
C[i, j] <- sum(A[i, ])+ sum(A[j, ])
}
}

Related

Apply a replacement to each 3rd dimension of a 3D array

I have an mxnxp (3D) array A. I have a 2D matrix B with values ranging from 1:m in the first column and 1:n in the second column. What I'd like to do is NA out the indices that correspond to those given by B in each of the third dimension (heights?). So,
for (i in 1:p) {
A[,,i][B] = NA
}
Is there a way to do this without a for loop? I was thinking something like
A_NA = apply(A,3,function(x) x[B] = NA)
But that doesn't work.
We need to return the x and then assign it back to 'A'
A[] <- apply(A,3,function(x) { x[B] = NA; x})
Checking with the OP's solution
for (i in 1:p) {
A1[,,i][B] = NA
}
identical(A, A1)
#[1] TRUE
data
A <- array(1:40, c(5, 4, 2) )
B <- cbind(c(1, 2, 3, 4), c(2, 3, 1, 1))
p <- 2
A1 <- A

Vectorized matrix and array multiplication in R

I could not figure out, how to write a vectorized version of the following matrix and array multiplication:
v = rep(0.1, 2)
v2 = matrix(0, nrow = 2, ncol = 3)
A = matrix(0.25, nrow = 2, ncol = 3)
R = matrix(- 1, nrow = 2, ncol = 3)
P = array(1:12, dim = c(2, 2, 3))
for (i in 1:3) {
v2[, i] = A[, i] * (R[, i] + P[, , i] %*% v)
}
v = rowSums(v2)
Can someone help?
The problem that we are faced with is that we want to do matrix multiplication over P, a 3d array. As this is not efficiently possible, it is better to transform this array to a 2d column matrix.
P <- array(1:12, dim = c(2, 2, 3))
P <- matrix(P, nrow = 2)
The A and R matrices don't have to be adjusted for this to work
A <- matrix(0.25, nrow = 2, ncol = 3)
R <- matrix(-1, nrow = 2, ncol = 3)
Matrix multiplication with the v vector can then be accomplished by transforming the column vector into a sparse block diagonal matrix with the bdiag(...) function from the Matrix package.
library(Matrix)
v <- rep(0.1, 2)
v <- bdiag(v, v, v)
## [1,] 0.1 . .
## [2,] 0.1 . .
## [3,] . 0.1 .
## [4,] . 0.1 .
## [5,] . . 0.1
## [6,] . . 0.1
This gives the same result as before, however, this time in a vectorized manner.
v <- rowSums(A * (R + (P %*% v)))
## [1] 0.15 0.30
Edit: In the above equation I use two types of multiplication: *, the dot-product, which computes the element-wise products between two matrices of equal size, and %*%, the ordinary matrix product, which computes the matrix product of two conformable matrices, or in other words, the number of columns of the first, and the number of rows of the second matrix should be equal.
Edit2: As requested I have included how to transform the given P array to a matrix.
Edit3: This method can be generalized by introducing a variable n for the number of groups. The key adjustment is in the declaration of the block diagonal matrix, as next to individual matrices, this function also takes a list of matrices as input. This results in the following solution
library(Matrix)
n <- 3
P <- array(1:12, dim = c(2, 2, n))
P <- matrix(P, nrow = 2)
A <- matrix(0.25, nrow = 2, ncol = n)
R <- matrix(-1, nrow = 2, ncol = n)
v <- rep(0.1, 2)
v <- bdiag(rep(list(v),n))
v <- rowSums(A * (R + (P %*% v)))
## [1] 0.15 0.30

Using a subscript within a for loop to store output in an array in R

I want to run a simulation with varying standard deviation (SD) values and store each simulation results along the rows using the following nested for loop. I am also using a user defined function QR to extract coefficients from results of Quanile Regression.
QR <- function(varname, data){
y <- data[, varname]
q <- summary(rq(y ~ x, taus), se = "boot")
z <- rbind(q[[1]]$coef, q[[2]]$coef, q[[3]]$coef, q[[4]]$coef)
}
taus <- c(.05, .1, .25, .75, .90, .95) # Quantiles to be extracted
nsim <- 10 # No of simulations
SD <- c(1, 3, 5) # Varying SD
res <- array(NA, dim = c(nsim, 10, 3)) # Empty array to store the results
for (i in 1:3){
for (j in 1:nsim){
x <- rnorm(SS[i], 10, 1);
eN <- rnorm(SS[i], 0, 1);
eLN1 <- rlnorm(SS[i], 0, 0.25);
data <- data.frame(cbind(y1 <- 1 + (2 * x) + eN,
y2 <- 1 + (2 * x) + eLN1,
x))
colnames(data) <- c("y1", "y2", "x")
listQR <- lapply(names(data)[1:2], function(x) QR(x, data))
res[j, 1, i] <- SS[i];
res[j, 2, i] <- SS[j];
res[j, 3, i] <- listQR[[1]][1, 1];
res[j, 4, i] <- listQR[[1]][1, 2];
res[j, 5, i] <- listQR[[1]][2, 1];
res[j, 6, i] <- listQR[[1]][2, 2];
res[j, 7, i] <- listQR[[2]][1, 1];
res[j, 8, i] <- listQR[[2]][1, 2];
res[j, 9, i] <- listQR[[2]][2, 1];
res[j, 10, i] <- listQR[[2]][2, 2];
write.csv(res, file = "test.csv");
}
}
I also have several other values to be extracted from listQR and store it the same way, in which case I have to write several other line of codes for them. My question is, can I use some subscript within the loop for listQR/modify the code so that I end up writing lesser line of codes? Something like,
res[j, k, i] <- listQR[[k]] # Tried this, end up overwriting the values
I have found a solution by customizing QR function to give relevant coefficients in a matrix format instead of extracting them within the loop. I used the following code.
QR <- function(varname, data){
y<-data[,varname]
q<-summary(rq(y~x, taus),se="boot")
z<-cbind(q[[1]]$coef[1,1], q[[2]]$coef[1,1],
q[[3]]$coef[1,1], q[[4]]$coef[1,1])
return(z)
}
taus <- c(.05,.1,.25,.75,.90,.95)
nsim<-10
SD<-c(1,3,5)
res<-array(NA,dim=c(nsim,10,3))
for (i in 1:3){
for (j in 1:nsim){
x<-rnorm(50,10,SD[i]); eN<-rnorm(50,0,SD[i]); eLN1<-rlnorm(50,0,SD[i]);
data<-data.frame(cbind(y1<-1+(2*x)+eN, y2<-1+(2*x)+eLN1, x))
colnames(data)<-c("y1", "y2","x")
listQR<-lapply(names(data)[1:2], function(x) QR(x, data))
write.csv(res, file="test.csv");
}
}

How to swap two row vectors inside a row vector?

i am trying to swap 2 row vectors which are inside a row vector.
For example:
a=[1 2 3];
b=[5 3];
c=[9 3 7 6];
d=[7 5];
X1= [ a, b , d, c ];
I want to do random swapping such that two of the a,b,c,d remains at the same position in X1 and the remaining two of them shuffles in X1. For example, some of the possible random swaps are:
[b,a,d,c] % a and b swap with each other whereas d and c remain at the same place
[d,b,a,c] % a and d swap with each other whereas b and c remain at the same place
[c,b,d,a] % a and c swap with each other whereas b and d remain at the same place
.....
.....
The proper and safe way to what you're trying to do is by assigning your variables to a cell, permuting the elements of the cell, and finally concatenating the result.
Imagine a specific permutation, say, [c, b, a, d]. This permutation can be coded as [3, 2, 1, 4] in terms of a mapping. The corresponding code to generate your array is then:
% generate input
a = [1, 2, 3];
b = [5, 3];
c = [9, 3, 7, 6];
d = [7, 5];
% generate cell to permute
tmpcell = {a, b, c, d};
% define our permutation
permnow = [3, 2, 1, 4];
% permute and concatenate the result into an array
result = [tmpcell{permnow}];
% check if this is indeed OK:
disp(isequal(result,[c, b, a, d])) % should print 1
The only thing you might still need is to generate a random configuration. This is easy: you just have to choose 2 random indices and swap them in [1, 2, 3, 4]. A lazy option to do this:
nvars = length(tmpcell); % generalizes to multiple variables this way
idperm = 1:nvars;
i1 = randi(nvars,1);
partperm = setdiff(idperm, i1); % vector of remaining indices, avoid duplication
i2 = partperm(randi(nvars-1,1)); % second index, guaranteed distinct from i1
permnow = idperm;
permnow([i1, i2]) = [i2, i1]; % swap the two indices

Define multiple variables at the same time in MATLAB

I want to define multiple variables at the same time.
For example, I want to define
a = 1
b = 2
c = 3
like this.
So I made a matrix with [a,b,c]:
x = [a, b, c];
y = [1, 2, 3];
x = y
So I want to get the following answer.
a = 1
b = 2
c = 3
If I use
[a, b, c] = deal(1, 2, 3)
then, I can get
a = 1
b = 2
c = 3
But I want to use matrix x instead of [a, b, c]
So if I use,
x = deal(1,2,3)
there is an error.
Is there any solution?
Maybe I don't understand the question but if you want to use the matrix x instead of [a, b, c] why don't you just define it as
x = [1, 2, 3];
From your question it sounds to me as if you are overcomplicating the problem. You begin by wanting to declare
a = 1;
b = 2;
c = 3;
but what you want instead according to the end of your question is
x = [1, 2, 3];
If you define x as above you can the refer to the individual elements of x like
>> x(1), x(2), x(3)
ans =
1
ans =
2
ans =
3
Now you have the best of both worlds with 1 definition. You can refer to a, b and c using x(1), x(2), x(3) instead and you've only had to define x once with x = [1, 2, 3];.
You cannot deal into a numeric array, but you can deal into a cell array and then concatenate all the elements in the cell array, like this:
[x{1:3}] = deal(1, 2, 3); % x is a cell array {1, 2, 3}
x = [x{:}]; % x is now a numeric array [1, 2, 3]

Resources