Creating a new dataframe with values calculated from another dataframe [duplicate] - r

I have a question about adding up the column of the matrix
for example:
I have a matrix
[,1] [,2] [,3]
[1,] 1 3 1
[2,] 2 4 2
I want it to be
[,1] [,2] [,3]
[1,] 1 4 5
[2,] 2 6 8

We can apply cumsum on each row by looping over the rows with apply and MARGIN specified as 1 and transpose the output
t(apply(m1, 1, cumsum))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
Or with a for loop
for(i in seq_len(ncol(m1))[-1]) m1[,i] <- m1[, i] + m1[, i-1]
Or another option is to split it a list of vectors with asplit and then Reduce with + and accumulate = TRUE
do.call(cbind, Reduce(`+`, asplit(m1, 2), accumulate = TRUE))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
or with a convenient function rowCumsums from matrixStats
library(matrixStats)
rowCumsums(m1)
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
data
m1 <- cbind(1:2, 3:4, 1:2)

Related

how to add up the column (cumulative sum) of the matrix in R?

I have a question about adding up the column of the matrix
for example:
I have a matrix
[,1] [,2] [,3]
[1,] 1 3 1
[2,] 2 4 2
I want it to be
[,1] [,2] [,3]
[1,] 1 4 5
[2,] 2 6 8
We can apply cumsum on each row by looping over the rows with apply and MARGIN specified as 1 and transpose the output
t(apply(m1, 1, cumsum))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
Or with a for loop
for(i in seq_len(ncol(m1))[-1]) m1[,i] <- m1[, i] + m1[, i-1]
Or another option is to split it a list of vectors with asplit and then Reduce with + and accumulate = TRUE
do.call(cbind, Reduce(`+`, asplit(m1, 2), accumulate = TRUE))
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
or with a convenient function rowCumsums from matrixStats
library(matrixStats)
rowCumsums(m1)
# [,1] [,2] [,3]
#[1,] 1 4 5
#[2,] 2 6 8
data
m1 <- cbind(1:2, 3:4, 1:2)

How do I create an addition table in R?

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

How to concatenate column repetitions of a matrix without a for loop

Let's say I have the below matrix:
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
I want to generate a matrix which is the concatenation (by column) of matrices that are generated by repetition of each column k times. For example, when k=3, below is what I want to get:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 2 2 2
[2,] 3 3 3 4 4 4
[3,] 5 5 5 6 6 6
How can I do that without a for loop?
You can do this with column indexing. A convenient way to repeat each column number the correct number of times is the rep function:
mat[,rep(seq_len(ncol(mat)), each=3)]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 1 1 1 2 2 2
# [2,] 3 3 3 4 4 4
# [3,] 5 5 5 6 6 6
In the above expression, seq_len(ncol(mat)) is the sequence from 1 through the number of columns in the matrix (you could think of it like 1:ncol(mat), except it deals nicely with some special cases like 0-column matrices).
Data:
(mat <- matrix(1:6, nrow=3, byrow = TRUE))
# [,1] [,2]
# [1,] 1 2
# [2,] 3 4
# [3,] 5 6
We can repeat each element of matrix k times and fit the vector in a matrix where number of columns is k times the original one.
k <- 3
matrix(rep(t(mat), each = k), ncol = ncol(mat) * k, byrow = TRUE)
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 1 1 1 2 2 2
#[2,] 3 3 3 4 4 4
#[3,] 5 5 5 6 6 6

How to sum two matrices by seq_along in r?

I have two matrices that i want to sum
mat1<-matrix(1:4,2,2)
mat2<-matrix(5:8,2,2)
mat1
[,1] [,2]
[1,] 1 3
[2,] 2 4
mat2
[,1] [,2]
[1,] 5 7
[2,] 6 8
what i want is this
mat_sum
[,1] [,2]
[1,] 6 10
[2,] 8 12
I tried
mat_sum <- sapply(seq_along(mat1), function(i)
mat1[[i]]+mat2[[i]])
but then it doesnt return a matrix
[1] 6 8 10 12
How can i get it to return a matrix?
We can do a regular + which will preserve the matrix format and does the elementwise summation
mat1 + mat2
# [,1] [,2]
#[1,] 6 10
#[2,] 8 12
If there are many matrices, place it in a list and use Reduce with +
Reduce(`+`, mget(paste0("mat", 1:2)))

Shuffle column values but keep the same matrix column ordering

How can I shuffle the values of matrix m1 across each column:
Initial:
m1=cbind(c(1,2,3),c(4,5,6),c(7,8,9))
Do something and:
m1=cbind(c(7,5,3),c(4,2,9),c(1,8,6))
Thanks
You can call the sample function on each column of your matrix to shuffle it:
set.seed(100)
apply(m1, 2, sample)
# [,1] [,2] [,3]
# [1,] 1 5 8
# [2,] 3 4 9
# [3,] 2 6 7
ehm, you mean by row in your example?!
shuffle a list:
# create a list from 1 to 9
x <- seq(1,9)
# shuffle
x[order(runif(length(x)))]
shuffle rows/columns of a matrix:
# example matrix
m1 <- matrix(x,ncol=3)
# shuffle by row
for (i in 1:nrow(m1)) m1[i,] <- m1[i,order(runif(length(m1[i,])))]
# shuffle by col
for (i in 1:ncol(m1)) m1[,i] <- m1[order(runif(length(m1[i,]))),i]
edit: maybe sample is better... http://stat.ethz.ch/R-manual/R-devel/library/base/html/sample.html
You can also put sample in matrix indices and sample the rows and columns.
To shuffle the entire matrix,
> m1[sample(nrow(m1)), sample(ncol(m1))]
# [,1] [,2] [,3]
#[1,] 6 9 3
#[2,] 5 8 2
#[3,] 4 7 1
Or by row
> m1[sample(nrow(m1)), ]
# [,1] [,2] [,3]
#[1,] 3 6 9
#[2,] 1 4 7
#[3,] 2 5 8
Or by column
> m1[,sample(ncol(m1))]
# [,1] [,2] [,3]
#[1,] 7 4 1
#[2,] 8 5 2
#[3,] 9 6 3

Resources