9

I have a matrix, like the one generated with this code:

> m = matrix(data=c(1:50), nrow= 10, ncol = 5);
> colnames(m) = letters[1:5];

If I filter the columns, and the result have more than one column, the new matrix keeps the names. For example:

> m[, colnames(m) != "a"];

       b  c  d  e
 [1,] 11 21 31 41
 [2,] 12 22 32 42
 [3,] 13 23 33 43
 [4,] 14 24 34 44
 [5,] 15 25 35 45
 [6,] 16 26 36 46
 [7,] 17 27 37 47
 [8,] 18 28 38 48
 [9,] 19 29 39 49
[10,] 20 30 40 50

Notice that here, the class is still matrix:

> class(m[, colnames(m) != "a"]);
[1] "matrix"

But, when the filter lets only one column, the result is a vector, (integer vector in this case) and the column name, is lost.

> m[, colnames(m) == "a"]
[1]  1  2  3  4  5  6  7  8  9 10

> class(m[, colnames(m) == "a"]);
[1] "integer"

The name of the column is very important.

I would like to keep both, matrix structure (a one column matrix) and the column's name.

But, the column's name is more important.

I already know how to solve this by the long way (by keeping track of every case). I'm wondering if there is an elegant, enlightening solution.

htellez
  • 1,269
  • 2
  • 13
  • 25
  • possible duplicate of [Why are R tables with 1 column accessed differently to those with more than 1?](http://stackoverflow.com/questions/7938883/why-are-r-tables-with-1-column-accessed-differently-to-those-with-more-than-1) – mnel Apr 04 '13 at 02:43
  • It does seem to crop up frequently. It's probably in "R Inferno", and it's certainly in the R-FAQ: 7.4 (http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-my-matrices-lose-dimensions_003f) and I answered a slightly more obscure version of it today on R-help: https://stat.ethz.ch/pipermail/r-help/2013-April/350790.html – IRTFM Apr 04 '13 at 03:32

2 Answers2

16

You need to set drop = FALSE. This is good practice for programatic use

drop

For matrices and arrays. If TRUE the result is coerced to the lowest possible dimension (see the examples)

m[,'a',drop=FALSE]

This will retain the names as well.

mnel
  • 113,303
  • 27
  • 265
  • 254
4

You can also use subset:

m.a = subset(m, select = colnames(m) == "a")
Alex
  • 15,186
  • 15
  • 73
  • 127