Duck
Duck

Reputation: 39605

Division of two matrix in R considering a matrix with only one row

Hi everybody I am working with matrix in R and I had a little problem trying to make a division between a 3x3 matrix with a 1x3 matrix. The two matrix I used are alfa and alfa2, they have the next structure (I add dput() version in the last part):

alfa
         jul 10  ago 10  sep 10
jul 10 28101696       0       0
ago 10 26558692 2048291       0
sep 10 25234674 2026633 3043638

alfa2
        jul 10  ago 10  sep 10
jul 10 1420547 2048291 3043638

I want to make a division between alfa and alfa2. Then I use this code alfa/alfa2 and I got this error:

Error in alfa/alfa2 : non-conformable arrays

With this division I want to get a new matrix like this:

         jul 10  ago 10  sep 10
jul 10 19.78230       0       0
ago 10 18.69610       1       0
sep 10 17.76405 0.98942       1

Where each column of alfa is divided by the correspondent column of alfa2. The dput() version of alfa and alfa2 is the next:

alfa
structure(c(28101696.45, 26558692.38, 25234673.68, 0, 2048291.06, 
2026632.72, 0, 0, 3043637.6), .Dim = c(3L, 3L), .Dimnames = list(
    c("jul 10", "ago 10", "sep 10"), c("jul 10", "ago 10", "sep 10"
    )))

alfa2
structure(c(1420547.36, 2048291.06, 3043637.6), .Dim = c(1L, 
3L), .Dimnames = list("jul 10", c("jul 10", "ago 10", "sep 10"
)))

Thanks for your help.

Upvotes: 1

Views: 251

Answers (3)

Roland
Roland

Reputation: 132706

t(t(alfa) / drop(alfa2))
#         jul 10    ago 10 sep 10
#jul 10 19.78230 0.0000000      0
#ago 10 18.69610 1.0000000      0
#sep 10 17.76405 0.9894261      1

Benchmarks:

library(microbenchmark)
microbenchmark(
t(t(alfa) / drop(alfa2)),
sweep(alfa, MARGIN = 2, STATS = alfa2, FUN = "/"),
t(apply(alfa,1,"/",alfa2))
)

# Unit: microseconds
#                                              expr    min      lq  median      uq     max neval
# t(t(alfa)/drop(alfa2))                            17.247 19.4030 20.9430 22.4830  97.934   100
# sweep(alfa, MARGIN = 2, STATS = alfa2, FUN = "/") 42.500 44.9640 45.8880 47.5820 227.282   100
# t(apply(alfa, 1, "/", alfa2))                     76.069 78.9945 80.3805 83.4605 177.390   100

set.seed(42)
alfa <- matrix(rnorm(1000), ncol=10)
alfa2 <- matrix(rnorm(10), ncol=10)

microbenchmark(
  t(t(alfa) / drop(alfa2)),
  sweep(alfa, MARGIN = 2, STATS = alfa2, FUN = "/"),
  t(apply(alfa,1,"/",alfa2))
)

# Unit: microseconds
#                                              expr     min       lq   median      uq      max neval
#                            t(t(alfa)/drop(alfa2))  25.870  27.7180  30.4895  31.722 1191.838   100
# sweep(alfa, MARGIN = 2, STATS = alfa2, FUN = "/")  60.362  64.2125  68.8320  73.913  164.456   100
#                     t(apply(alfa, 1, "/", alfa2)) 288.259 311.9730 326.4470 383.267 1912.176   100

Upvotes: 0

James
James

Reputation: 66844

You can use apply to divide row-wise, but you need to transpose at the end.

t(apply(alfa,1,"/",alfa2))
           [,1]      [,2] [,3]
jul 10 19.78230 0.0000000    0
ago 10 18.69610 1.0000000    0
sep 10 17.76405 0.9894261    1

Upvotes: 0

dickoa
dickoa

Reputation: 18437

You can use sweep for this task

sweep(alfa, MARGIN = 2, STATS = alfa2, FUN = "/")
##        jul 10  ago 10 sep 10
## jul 10 19.782 0.00000      0
## ago 10 18.696 1.00000      0
## sep 10 17.764 0.98943      1

Upvotes: 4

Related Questions