max
max

Reputation: 4521

Stop `apply` from converting matrix into vector in R?

library(tidyverse)

Assume we have this matrix. I want the quantiles for each row.

m <- matrix(1:12, nrow=4)

     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

If I use apply on quantile with two arguments, it works as expected:

m %>% 
  apply(1, quantile, probs = c(0.05, 0.9)) %>%
  t

      5%  90%
[1,] 1.4  8.2
[2,] 2.4  9.2
[3,] 3.4 10.2
[4,] 4.4 11.2

However, if I supply only 1 argument to quantile, the output is converted to a vector.

m %>% 
  apply(1, quantile, probs = c(0.05)) %>%
  t

     [,1] [,2] [,3] [,4]
[1,]  1.4  2.4  3.4  4.4

How can I keep the output as a matrix with the proper column names?

Upvotes: 1

Views: 199

Answers (1)

Andrew Brown
Andrew Brown

Reputation: 1065

OK. First of all, your second result is a matrix, it just is missing the column names because of the default simplification behavior of apply. To get around this, use sapply(simplify=FALSE) or lapply

# for %>%
library(magrittr, warn.conflicts = FALSE)

m <- matrix(1:12, nrow=4)
res1 <- m %>% 
  apply(1, quantile, probs = c(0.05, 0.9)) %>%
  t
colnames(res1)
#> [1] "5%"  "90%"

res2 <- m %>% 
  apply(1, quantile, probs = c(0.05)) %>%
  t

colnames(res2)
#> NULL

# res2 is a matrix
inherits(res2, 'matrix')
#> [1] TRUE

# to keep the column names, use lapply then rbind
do.call('rbind', lapply(1:nrow(m), function(i) quantile(m[i,], probs = 0.05)))
#>       5%
#> [1,] 1.4
#> [2,] 2.4
#> [3,] 3.4
#> [4,] 4.4

Created on 2020-12-03 by the reprex package (v0.3.0)

Upvotes: 1

Related Questions