Amberopolis
Amberopolis

Reputation: 455

rbind within mapply returns transposed dimensions

I have seen a couple related questions on this topic, for instance here and here but the solutions don't seem to work for me as far as I can tell.

I have a function that returns a 5x3 matrix. I use mapply to iterate the function 4 times. My goal is to have the mapply call return a 20x3 matrix, but instead it returns a 15x4 matrix.

population <- runif(100, 0, 1)
iterations <- seq(1:4)

test.func <- function(k){
    samp1 <- sample(population, 20, replace = FALSE)
    samp2 <- sample(population, 20, replace = FALSE)
    samp3 <- sample(population, 20, replace = FALSE)

    ## Pre-allocate 
    c1 <- NULL
    c2 <- NULL
    c3 <- NULL

    for (i in 1:5){
       c1[i] <- samp1[i]
       c2[i] <- samp2[i]
       c3[i] <- samp3[i]
    }

combined <- cbind(c1, c2, c3)
print(combined)
}

results <- mapply(FUN = test.func, k = iterations)

I tried a transpose within the function, but that didn't help. I'd be open to options that fix the problem after calling mapply too.

One alternative would be to convert the 5x3 matrices to data frames and then separate them into a 3x20 matrix and transpose it. But I am hoping there is a more sensible way.

Upvotes: 0

Views: 247

Answers (1)

Rich Scriven
Rich Scriven

Reputation: 99351

mapply is a multivariate version of sapply, which simplifies its result using simplify2array (unless you tell it otherwise). You don't need to use mapply since you only have one variable being passed to your function (actually, you have no variables being passed - see below). In base R, you can use

do.call(rbind, lapply(iterations, test.func)) 

Other options that can replace do.call(rbind, ...) are data.table::rbindlist and plyr::rbind.fill

Also, you're never passing k into the function, so you could even use replicate. But again, since replicate is essentially sapply you'd need simplify = FALSE

test.func()  ## notice that k is not used at all
#             c1         c2         c3
# [1,] 0.6087179 0.04439165 0.11227567
# [2,] 0.8915234 0.79688365 0.02446302
# [3,] 0.5635389 0.17794940 0.16731767
# [4,] 0.7040224 0.17201792 0.28175588
# [5,] 0.8999534 0.28175588 0.58302149

PS - I also condensed your last two lines in to one

combined <- cbind(c1, c2, c3)
print(combined)

can just be

cbind(c1, c2, c3)

That print call can make things frustrating when you assign x <- test.func()

Upvotes: 2

Related Questions