Reputation: 575
Is there an elegant way to add multiple copies of the same row to a matrix ? Below is an example that solves the problem. However, this example is slow and not elegant coding.
m <- matrix(c(1,2,3,4,5,6,7,8,9),ncol=3)
m0 <- m
r <- c(10,20,30)
#Correct example
for (i in c(1,2))
m[i,] <- r
print(m)
# [,1] [,2] [,3]
#[1,] 10 20 30
#[2,] 10 20 30
#[3,] 3 6 9
#Attempts below look straightforward but lead to incorrect results
m <- m0
m[1:2,] <- apply(m[1:2,],1,function(x)r)
print(m)
# [,1] [,2] [,3]
#[1,] 10 30 20
#[2,] 20 10 30
#[3,] 3 6 9
m <- m0
m[1:2,] <- r
print(m)
# [,1] [,2] [,3]
#[1,] 10 30 20
#[2,] 20 10 30
#[3,] 3 6 9
Upvotes: 0
Views: 73
Reputation: 575
As to my knowledge, the for-loop is the fastest way to solve the problem. A faster solution would be to select a different data structure in R, where the records are in the columns instead of in the rows.
Below are speed measurements for the solutions by @docendo-discimus and me and an additional example where the records are in the columns instead of in the rows. Direct assignment works without errors in that case.
m <- matrix(c(1,2,3,4,5,6,7,8,9),ncol=3)
m0 <- m
r <- c(10,20,30)
#For loop
print(
system.time(
for (k in 1:100000){
for (i in c(1,2))
m[i,] <- r
}))
print(m)
# User System verstrichen
# 0.524 0.011 0.552
# [,1] [,2] [,3]
# [1,] 10 20 30
# [2,] 10 20 30
# [3,] 3 6 9
#@docendo-discimus: Create new matrix
m <- m0
print(
system.time(
for (k in 1:100000){
m[1:2, ] <- matrix(r, ncol = 3, nrow = 2, byrow = TRUE)})
)
print(m)
# User System verstrichen
# 0.818 0.011 0.833
# [,1] [,2] [,3]
# [1,] 10 20 30
# [2,] 10 20 30
# [3,] 3 6 9
#@docendo-discimus Transpose, modify columns, transpose again
m <- m0
print(
system.time(
for (k in 1:100000){
m <- t(m)
m[, 1:2] <- r
m <- t(m)
m}))
print(m)
# User System verstrichen
# 1.870 0.010 1.895
# [,1] [,2] [,3]
# [1,] 10 20 30
# [2,] 10 20 30
# [3,] 3 6 9
#Usage of different data structure with a transposed matrix
m <- matrix(c(1,2,3,4,5,6,7,8,9),nrow=3)
m0 <- m
print(m)
# [,1] [,2] [,3]
# [1,] 1 4 7
# [2,] 2 5 8
# [3,] 3 6 9
print(
system.time(
for (k in 1:100000){
m[,1:2] <- r
}))
print(m)
# User System verstrichen
# 0.241 0.013 0.255
# [,1] [,2] [,3]
# [1,] 10 10 7
# [2,] 20 20 8
# [3,] 30 30 9
Upvotes: 0
Reputation: 70256
You could construct a second matrix from the vector r
and insert it into m
as follows:
m[1:2, ] <- matrix(r, ncol = 3, nrow = 2, byrow = TRUE)
m
# [,1] [,2] [,3]
#[1,] 10 20 30
#[2,] 10 20 30
#[3,] 3 6 9
Another option is to t
ranspose m
, insert r
and t
ranspose again:
m <- t(m)
m[, 1:2] <- r
m <- t(m)
m
# [,1] [,2] [,3]
#[1,] 10 20 30
#[2,] 10 20 30
#[3,] 3 6 9
I haven't benchmarked the performance, though.
Upvotes: 1