Discrete difference operator for a Matrix in R? - r

I have a matrix
A <- matrix(1:16, nrow = 4, ncol = 4, Byrow = FALSE)
I want a row-wise difference of matrix A. That is take element-wise difference between the first and second rows of A, element-wise difference between the second and third rows of A, etc. Since A ∈ R4×4, the resulting matrix should contain row-wise differences which has a dimension of 3 × 4.
Instead of using for-loop to iterate over the rows of A and take differences between consecutive rows, I would like to use the discrete difference operator to speed up the operation. I use sapply() to construct this matrix difference operator B. Then use B × A to compute the row-wise difference.
Let's say Matrix B ∈ R3×4
B <- matrix(c( -1, 1, 0, 0,
0, -1, 1, 0,
0, 0, -1, 1), nrow = 3, ncol = 4, byrow = TRUE)
Expected output be a matrix C ∈ R3×4 with all 1's.
Result_C <- matrix(c( 1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1), nrow = 3, ncol = 4, byrow = TRUE)
How should I proceed? and what is difference operator for a Matrix in R?

We can use diff to calculate the difference between the rows
diff(A)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 1 1 1 1
#[3,] 1 1 1 1

You can adress to full columns or rows of the matrix
A <- matrix(1:16, nrow = 4, ncol = 4)
A[2:(nrow(A)),]-A[1:(nrow(A)-1),]
and yes, diff(A) should do the same here

Related

what is the difference and what does each of the functions exactly do? Why aren't they the same?

polyEval should represent a polynomial equation. For example, polyEval(x = 2, a = c(2, 3, 1)) is supposed to return 12, whereas polyEval(1, c(0, 1, 0, 1, 0, 1)) is supposed to return 3. This is the case for the first polyEval function, but why isn't it for the second? What exactly is the second one doing wrong? Because in my understanding, they should work the same.
polyEval <- function(x,a) {
n <- 1:length(a)
return(sum(c(a[n]*x^(n-1))))
}
polyEval <- function(x,a) {
sum(a*(x^(0:(length(a)))))
}
After correction, both raise x to the power 0, 1, 2, ..., length(a)-1 and then multiply the resulting vector by a and sum.
In the second one length(a) should be length(a)-1.
polyEval2 <- function(x,a) {
sum(a*(x^(0:(length(a)-1))))
}
polyEval2(2, c(2, 3, 1))
## [1] 12
polyEval2(1, c(0, 1, 0, 1, 0, 1))
## [1] 3

Add columns of matrix to columns of other matrix in R

I have a simple question, but couldn't figure out a good solution. So hope, somebody can help :)
I want to add each column of a matrix B to a column of a matrix A, where an index vector specifies, to which column of A this column should be added to. So it is possible that more than one column of B is added to the same column of A. I want to accumulate these changes and not replace these.
This is a working solution with a for loop:
A <- matrix(0, ncol = 4, nrow = 4)
B <- matrix(c(1, 0, 0, 0, 2, 0, 1, 2, 0, 1, 1, 0), ncol = 3)
cols <- c(1, 2, 2)
for (i in seq_len(ncol(B))) {
A[, cols[i]] <- A[, cols[i]] + B[, i]
}
print(A)
I thought I could write this without a for loop using
A <- matrix(0, ncol = 4, nrow = 4)
B <- matrix(c(1, 0, 0, 0, 2, 0, 1, 2, 0, 1, 1, 0), ncol = 3)
cols <- c(1, 2, 2)
A[, cols] <- A[, cols] + B
print(A)
But this doesn't return the same matrix, because it adds the second column of B to the second column of A but then in the next step replaces this with the third column of B instead of adding both of the replacements together.
I'm looking for a fast and general solution, which works also for different index vectors and matrices.
This doesn't eliminate the loop, but it does make it shorter:
A <- matrix(0, ncol = 4, nrow = 4)
B <- matrix(c(1, 0, 0, 0, 2, 0, 1, 2, 0, 1, 1, 0), ncol = 3)
cols <- c(1, 2, 2)
for(i in unique(cols)){
A[, i] <- A[, i] + apply(as.matrix(B[, cols == i]), 1, sum)
}
print(A)
Try this
ans = A[,cols] + B
ans = sapply(split(1:NCOL(ans), cols), function(i) rowSums(ans[, i, drop = FALSE]))
inds = cbind(rep(1:NROW(A), length(unique(cols))), rep(unique(cols), each = NROW(A)))
replace(A, inds, ans[inds])
# [,1] [,2] [,3] [,4]
#[1,] 1 2 0 0
#[2,] 0 1 0 0
#[3,] 0 2 0 0
#[4,] 0 2 0 0

Creating a vector with certain values at specific positions based on another vector

If I start with vector1, and test to see which items equal 1:
vector1 <- c(0, 1, 1, 1, 0, 1, 1, 1, 0, 1)
test <- which(vector1 == 1)
test now equals: 2, 3, 4, 6, 7, 8, 10
then, I want to randomly choose two of the items in test:
sample_vector <- sample(test, 2, replace = FALSE)
the above code generated a sample_vector: 6, 3
My question is how do I take sample_vector and turn it into:
vector2 <- 0, 0, 1, 0, 0, 1, 0, 0, 0, 0
I'm essentially looking to assign only the items in sample_vector to equal 1, and the remaining items from vector1 are assigned to equal 0 (i.e. so it looks like vector2). vector2 needs to have the same length at vector1 (10 items).
Thanks!
vector2 <- rep(0, length(vector1))
vector2[sample_vector] <- 1
set.seed(44)
vector1 <- c(0, 1, 1, 1, 0, 1, 1, 1, 0, 1)
test <- which(vector1 == 1)
sample_vector <- sample(test, 2, replace = FALSE)
sample_vector
#[1] 8 3
replace(tabulate(seq_along(vector1)) - 1, sample_vector, 1)
#[1] 0 0 1 0 0 0 0 1 0 0
Use this code.
vector2 <- rep(0,len(vector1))
vector2[sample_vector] = 1

r - apply binary vector mask on vector

How to filter vector v with mask m as example below?
v = c(1, 2, 3, 4, 5)
m = c(1, 0, 0, 1, 1)
# apply mask m on v (0 should subtract element)
maskedVector # [1, 4, 5]
You can transform your m vector to a logical object and use it to index v.
v = c(1, 2, 3, 4, 5)
m = c(1, 0, 0, 1, 1)
v[as.logical(m)]
[1] 1 4 5

How do I add columns to expand a matrix in R

Sorry I couldn't think of a more informative title, but here's my challenge. I have a matrix and I need to add columns in specific places based on parameters described by a vector. For example, if I have the following matrix:
1, 0, 1, 2, 0
0, 0, 1, 1, 1
1, 1, 0, 0, 0
2, 0, 1, 0, 2
but for a particular R package (unmarked), I need to add columns of NA in specific place. I have a vector relating the columns in the matrix:
1, 1, 1, 2, 3
Which indicates that columns 1-3 were from the same sampling period and columns 4 and 5 were from different sampling periods. I need to make the number of columns in the matrix equal the max number from the same sampling period times the number of sampling periods. In this case there are three 1s (max number of any unique value in the vector) and a total of three sampling periods (max number in the vector). So I need a matrix with 9 columns (3 x 3). Specifically, I need to add the new columns of NAs after the 4th and 5th columns. Basically, I just need columns of NAs to be placeholders to have a matrix where the number of observations (each column) is the same (=3) for each of the sample periods (indicated by the number in the vector). This is difficult to describe but in this imaginary example I would want to end up with:
1, 0, 1, 2, NA, NA, 0, NA, NA
0, 0, 1, 1, NA, NA, 1, NA, NA
1, 1, 0, 0, NA, NA, 0, NA, NA
2, 0, 1, 0, NA, NA, 2, NA, NA
this would be described by a vector that looked like:
1, 1, 1, 2, 2, 2, 3, 3, 3
although I don't actually need to produce that vector, just the matrix. Obviously, it was easy to add those columns in this case, but for my data I have a much bigger matrix that will end up with ~200 columns. Plus I will likely have to do this for numerous data sets.
Can anyone help me with a way to code this in R so that I can automate the process of expanding the matrix?
Thanks for any advice or suggestions!
EDIT:
to make things a bit more similar to my actual data here is a reproducible matrix and vector similar to my current ones:
m <- matrix(rpois(120*26, 1), nrow = 120, ncol = 26)
v <- c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7)
Assuming m is the matrix and v is the vector, you can use something like
t = table(v)
size = dim(m)[1] * max(t) # size of each block based on the longest
matrix(unlist(lapply(names(t), function(i) {
x = m[, v == i] # get the short block
c(x, rep(NA, size - length(x))) # extend it to size
})), dim(m)[1])
To modify the matrix just as you asked assuming the matrix is mat:
nr <- nrow(mat)
nas <- rep(NA, nr)
l <- lapply( 4:ncol(mat), function(x) matrix(c(mat[,x],nas,nas), nrow = nr) )
cbind(mat[,1:3], do.call(cbind,l))

Resources