0

I'm trying to generate this matrix without using a for loop (to speed up the processing time):

       Module 1 Module 2 Module 3
y0       20       20       20
y1       20       20       20
y0       40       40       40
y1       40       40       40
y0       60       60       60
y1       60       60       60
y0       80       80       80
y1       80       80       80
y0      100      100      100
y1      100      100      100
y0      120      120      120
y1      120      120      120
y0      140      140      140
y1      140      140      140
y0      160      160      160
y1      160      160      160
y0      180      180      180
y1      180      180      180
y0      200      200      200
y1      200      200      200

I have been attempting the apply functions, replicate() and do.call(). I've ended up with this code:

a = 10          # Number of increments
n1 = 100       # Sample size
m.fn <- function(n1, a) {
  b <- matrix(rep(n1), nrow = 2, ncol = 3)
  rownames(b) <- c("y0", "y1")
  c <- do.call(rbind, replicate(a, b, simplify=FALSE))

  colnames(c) <- c("Module 1", "Module 2", "Module 3")
  return(c)
}

Which produces a matrix similar to above, but with all entries as 20.

I've tried replacing the values with little success, as per below:

 a = 10          # Number of increments
 n1 = 100       # Sample size
    m.fn <- function(n1, a) {
      b <- matrix(rep(n1), nrow = 2, ncol = 3)
      rownames(b) <- c("y0", "y1")
      c <- do.call(rbind, replicate(a, b, simplify=FALSE))
      c[3:(2 * a),] <- (n1 * seq(3, 2 * a))
      colnames(c) <- c("Module 1", "Module 2", "Module 3")
      return(c)
    }

This is what results:

       Module 1 Module 2 Module 3
y0       20       20       20
y1       20       20       20
y0       60       60       60
y1       80       80       80
y0      100      100      100
y1      120      120      120
y0      140      140      140
y1      160      160      160
y0      180      180      180
y1      200      200      200
y0      220      220      220
y1      240      240      240
y0      260      260      260
y1      280      280      280
y0      300      300      300
y1      320      320      320
y0      340      340      340
y1      360      360      360
y0      380      380      380
y1      400      400      400

For reference, this is the code that I used to create my desired matrix, involving a for loop:

    n.fn <- function(n1, a) {
  b <- matrix(rep(1, 3), nrow = 1, ncol = 3)
  for (no in 1:a) {
    c <- matrix(rep(n1 * no, 6), nrow = 2, ncol = 3)
    rownames(c) <- c("y0", "y1")
    b <- rbind(b, c)
  }
  b <- as.matrix(b[-1, 1:3])
  colnames(b) <- c("Module 1", "Module 2", "Module 3")
  return(b)
}
n <- n.fn(n1, a)

Any help with creating the first matrix, without the use of a for loop, would be gratefully appreciated!

MBorg
  • 1,345
  • 2
  • 19
  • 38
  • `replicate(3, lapply(seq(20,200,20), rep, 2) %>% unlist)` – Adam Quek Nov 07 '17 at 06:48
  • Thank you for your reply. This isn't working for me. I get the response: > replicate(3, lapply(seq(20, 200, 20), rep, 2) %>% unlist) Error in lapply(seq(20, 200, 20), rep, 2) %>% unlist : could not find function "%>%" – MBorg Nov 07 '17 at 07:15
  • 1
    You need to load the install and use the library `dplyr` to make use of the pipe. Alternatively, just run `replicate(3, unlist(lapply(seq(20,200,20), rep, 2) ))`. Yay for bracket galore! – Adam Quek Nov 07 '17 at 07:19
  • Thanks Adam. %>% works now, and your code works perfectly. And it generates the list I'm after! – MBorg Nov 07 '17 at 07:36

1 Answers1

1

You can just generate the sequence from 20 to 400, repeat it as many times as there are columns times and arrange in a matrix:

 df <- matrix(rep(rep(seq(from = 20, to = 400, by = 20), each = 2), times = 3), ncol = 3)

Another way is per Adam Quek suggestion using replicate:

df <- replicate(3, unlist(lapply(seq(20,200,20), rep, 2) )) 

Now just give it the desired column and row names:

colnames(df) <- paste("Module", 1:ncol(df))
rownames(df) <- rep(paste0("y", 0:1), nrow(df)/2)
missuse
  • 19,056
  • 3
  • 25
  • 47
  • Thank you for your reply. This does generate a data frame / matrix, but not the one I'm after. I'm a data frame / matrix that has 2 rows of 20, then 2 rows of 40. Every 1st row is called "y0" and every 2nd row is called "y1." I've included it at the top of my original post. Your suggestion, though helpful, generates rows of 20 ascending each time, and the names are y1, y2, y3 etc – MBorg Nov 07 '17 at 07:16
  • @Matthew Borg check edit please, I trust I fixed the problem – missuse Nov 07 '17 at 07:19
  • Thanks missuse. Your suggestion and edits worked splendidly! I also appreciate you coming back to edit your suggestion! – MBorg Nov 07 '17 at 07:30