mat_sub <- function(x){
nc <- ncol(x)
for (i in 1:nc){
s <- x[,i]-x[,i-1]
}
Z <- cbind(x,s)
Z}
Please help in understanding where I am doing wrong.
As stated in comments you need to start the for loop at the second column, else i - 1 gets zero and that can't be subsetted. The other issue is s which gets overwritten in each iteration. You want to define a two-dimensional array (i.e. a matrix) beforehand, with dimensions of your original matrix minus one column, that gets filled in each iteration.
You may want to correct your code to:
mat_sub <- function(x) {
nc <- ncol(x)
s <- array(NA, dim(x))[, -nc]
for (i in 2:nc) {
s[, i - 1] <- x[, i] - x[, i - 1]
}
Z <- cbind(x, s)
Z
}
m <- matrix(1:12, 3, 4)
mat_sub(m)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] 1 4 7 10 3 3 3
# [2,] 2 5 8 11 3 3 3
# [3,] 3 6 9 12 3 3 3
Alternatively, in R you may simply do vectorized calculations including subtracting matrices.
cbind(m, m[, -1] - m[, -ncol(m)])
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] 1 4 7 10 3 3 3
# [2,] 2 5 8 11 3 3 3
# [3,] 3 6 9 12 3 3 3
You are over-writing s every time in the loop. Also you start the loop with 1 in which case there is no i-1 i.e 0th column.
You can try :
mat_sub <- function(x){
nc <- ncol(x)
x[, 2:nc] - x[, 1:(nc-1)]
}
Using an example :
set.seed(123)
mat <- matrix(sample(16), 4)
mat
# [,1] [,2] [,3] [,4]
#[1,] 15 10 4 11
#[2,] 16 2 12 13
#[3,] 3 6 7 8
#[4,] 14 5 1 9
mat_sub(mat)
# [,1] [,2] [,3]
#[1,] -5 -6 7
#[2,] -14 10 1
#[3,] 3 1 1
#[4,] -9 -4 8
I am trying to draw a variable number of samples for each of n attempts. In this example n = 8 because length(n.obs) == 8. Once all of the samples have been drawn I want to combine them into a matrix.
Here is my first attempt:
set.seed(1234)
n.obs <- c(2,1,2,2,2,2,2,2)
my.samples <- sapply(1:8, function(x) sample(1:4, size=n.obs[x], prob=c(0.1,0.2,0.3,0.4), replace=TRUE))
my.samples
This approach produces a list.
class(my.samples)
#[1] "list"
I identify the number of columns needed in the output matrix using:
max.len <- max(sapply(my.samples, length))
max.len
#[1] 2
The output matrix can be created using:
corrected.list <- lapply(my.samples, function(x) {c(x, rep(NA, max.len - length(x)))})
output.matrix <- do.call(rbind, corrected.list)
output.matrix[is.na(output.matrix)] <- 0
output.matrix
# [,1] [,2]
#[1,] 4 3
#[2,] 3 0
#[3,] 3 2
#[4,] 3 4
#[5,] 4 3
#[6,] 3 3
#[7,] 3 4
#[8,] 1 4
The above approach seems to work fine as along as n.obs includes multiple values and at least one element in n.obs > 1. However, I want the code to be flexible enough to handle each of the following n.obs:
The above sapply statement returns a 2 x 8 matrix with the following n.obs.
set.seed(1234)
n.obs <- c(2,2,2,2,2,2,2,2)
The above sapply statement returns an integer with the following n.obs.
set.seed(3333)
n.obs <- c(1,1,1,1,1,1,1,1)
The above sapply statement returns a list with the following n.obs.
n.obs <- c(0,0,0,0,0,0,0,0)
Here are example desired results for each of the above three n.obs:
desired.output <- matrix(c(4, 3,
3, 3,
2, 3,
4, 4,
3, 3,
3, 3,
4, 1,
4, 2), ncol = 2, byrow = TRUE)
desired.output <- matrix(c(2,
3,
4,
2,
3,
4,
4,
1), ncol = 1, byrow = TRUE)
desired.output <- matrix(c(0,
0,
0,
0,
0,
0,
0,
0), ncol = 1, byrow = TRUE)
How can I generalize the code so that it always returns a matrix with eight rows regardless of the n.obs used as input? One way would be to use a series of if statements to handle problematic cases, but I thought there might be a simpler and more efficient solution.
We can write a function :
get_matrix <- function(n.obs) {
nr <- length(n.obs)
my.samples <- sapply(n.obs, function(x)
sample(1:4, size=x, prob=c(0.1,0.2,0.3,0.4), replace=TRUE))
max.len <- max(lengths(my.samples))
mat <- matrix(c(sapply(my.samples, `[`, 1:max.len)), nrow = nr, byrow = TRUE)
mat[is.na(mat)] <- 0
mat
}
Checking output :
get_matrix(c(2,1,2,2,2,2,2,2))
# [,1] [,2]
#[1,] 1 4
#[2,] 4 0
#[3,] 4 3
#[4,] 4 4
#[5,] 4 2
#[6,] 4 3
#[7,] 4 4
#[8,] 4 4
get_matrix(c(1,1,1,1,1,1,1,1))
# [,1]
#[1,] 4
#[2,] 4
#[3,] 3
#[4,] 4
#[5,] 2
#[6,] 4
#[7,] 1
#[8,] 4
get_matrix(c(0,0,0,0,0,0,0,0))
# [,1]
#[1,] 0
#[2,] 0
#[3,] 0
#[4,] 0
#[5,] 0
#[6,] 0
#[7,] 0
#[8,] 0
You could Vectorize the sample function on the size= argument.
samplev <- Vectorize(sample, "size", SIMPLIFY=F)
Wrap samplev into a function and assign maximal length using length<- in an lapply.
FUN <- function(n.obs, prob.=c(.1,.2,.3,.4)) {
s <- do.call(rbind, lapply(
samplev(1:4, size=n.obs, prob=prob., replace=TRUE),
`length<-`, max(n.obs)))
if (!all(dim(s))) matrix(0, length(n.obs))
else ({s[is.na(s)] <- 0; s})
}
Results:
set.seed(1234)
FUN(c(2,1,2,2,2,2,2,2))
# [,1] [,2]
# [1,] 4 3
# [2,] 3 0
# [3,] 3 2
# [4,] 3 4
# [5,] 4 3
# [6,] 3 3
# [7,] 3 4
# [8,] 1 4
FUN(c(2,2,2,2,2,2,2,2))
# [,1] [,2]
# [1,] 2 4
# [2,] 4 4
# [3,] 4 4
# [4,] 4 4
# [5,] 4 4
# [6,] 2 3
# [7,] 1 2
# [8,] 4 3
FUN(c(1,1,1,1,1,1,1,1))
# [,1]
# [1,] 4
# [2,] 4
# [3,] 3
# [4,] 4
# [5,] 2
# [6,] 4
# [7,] 4
# [8,] 1
FUN(c(0,0,0,0,0,0,0,0))
# [,1]
# [1,] 0
# [2,] 0
# [3,] 0
# [4,] 0
# [5,] 0
# [6,] 0
# [7,] 0
# [8,] 0
FUN(c(3, 4))
# [,1] [,2] [,3] [,4]
# [1,] 2 3 3 0
# [2,] 4 3 4 3
I want you to help me about R code.
I have an object, M(list & array). Like this.
object1 <- array(0, c(2,2,2))
M <- list(object1, object1)
Then, I want to reshape m(vector) into M structure.
m <- c(1:16)
When M is list & matrix object, I can use 'relist' function. However, I can't use it to array object. How can I reshape m into M structure??
We can specify the dims in array and use relist
lapply(relist(m, skeleton = M), array, dim(object1))
#[[1]]
#, , 1
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#, , 2
# [,1] [,2]
#[1,] 5 7
#[2,] 6 8
#[[2]]
#, , 1
# [,1] [,2]
#[1,] 9 11
#[2,] 10 12
#, , 2
# [,1] [,2]
#[1,] 13 15
#[2,] 14 16
Or another option is
lapply(setNames(split(m, (seq_along(m)-1) %/% lengths(M)[1]), NULL), array, dim(object1))
#[[1]]
#, , 1
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#, , 2
# [,1] [,2]
#[1,] 5 7
#[2,] 6 8
#[[2]]
#, , 1
# [,1] [,2]
#[1,] 9 11
#[2,] 10 12
#, , 2
# [,1] [,2]
#[1,] 13 15
#[2,] 14 16
NOTE: Both the solutions are one-line solutions
This should be easy but I can't think of a more elegant way to create an addition table, such as:
x <- 1:3
cbind(x + x[1], x + x[2], x + x[3])
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 3 4 5
[3,] 4 5 6
I tried various versions of lapply() to no avail.
You can either use outer or sapply or expand.grid (in combination with rowSums)
x = 1:3
outer(x, x, "+")
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
sapply(seq_along(x), function(i) sapply(seq_along(x), function(j) x[i]+x[j]))
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
matrix(rowSums(expand.grid(x, x)), ncol = length(x))
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
You could do this:
m <- diag(length(x))
m[] <- x[col(m)] + x[row(m)]
# [,1] [,2] [,3]
#[1,] 2 3 4
#[2,] 3 4 5
#[3,] 4 5 6
OR
matrix(x,length(x),length(x),byrow = TRUE) + x
First create a "row" vector and a "column" vector in R:
> row.vector <- seq(from = 1, length = 4, by = 1)
> col.vector <- {t(seq(from = 1, length = 3, by = 2))}
From that I'd like to create a matrix by, e.g., multiplying each value in the row vector with each value in the column vector, thus creating from just those two vectors:
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 6 10
[3,] 3 9 15
[4,] 4 12 20
Can this be done with somehow using apply()? sweep()? ...a for loop?
Thank you for any help!
Simple matrix multiplication will work just fine
row.vector %*% col.vector
# [,1] [,2] [,3]
# [1,] 1 3 5
# [2,] 2 6 10
# [3,] 3 9 15
# [4,] 4 12 20
You'd be better off working with two actual vectors, instead of a vector and a matrix:
outer(row.vector,as.vector(col.vector))
# [,1] [,2] [,3]
#[1,] 1 3 5
#[2,] 2 6 10
#[3,] 3 9 15
#[4,] 4 12 20
Here's a way to get there with apply. Is there a reason why you're not using matrix?
> apply(col.vector, 2, function(x) row.vector * x)
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 6 10
## [3,] 3 9 15
## [4,] 4 12 20