4

Given a matrix with one row, one column, or one cell, I need to reorder the rows while keeping the matrix structure. I tried adding drop=F but it doesn't work! What did I do?

test = matrix(letters[1:5]) # is a matrix
test[5:1,,drop=F]           # not a matrix

test2 = matrix(letters[1:5],nrow=1) # is a matrix
test2[1:1,,drop=F]                  # not a matrix

test3 = matrix(1)  # is a matrix
test3[1:1,,drop=F] # not a matrix
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
dasf
  • 1,035
  • 9
  • 16

3 Answers3

7

I'd guess it was an overwritten F; F can be set as a variable, in which case it's no longer false. Always write out FALSE fully, it can't be set as a variable.

See Is there anything wrong with using T & F instead of TRUE & FALSE?

Also the R Inferno, section 8.1.32, is a good reference.

> F <- 1
> test = matrix(letters[1:5]) # is a matrix
> test[5:1,,drop=F]           # not a matrix
[1] "e" "d" "c" "b" "a"
> test[5:1,,drop=FALSE]       # but this is a matrix
     [,1]
[1,] "e" 
[2,] "d" 
[3,] "c" 
[4,] "b" 
[5,] "a" 
> rm(F)
> test[5:1,,drop=F]           # now a matrix again
     [,1]
[1,] "e" 
[2,] "d" 
[3,] "c" 
[4,] "b" 
[5,] "a" 
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
2

The code in your question works fine in a fresh R session:

test = matrix(letters[1:5]) # is a matrix
result = test[5:1,,drop=F]  
result
#      [,1]
# [1,] "e" 
# [2,] "d" 
# [3,] "c" 
# [4,] "b" 
# [5,] "a" 
class(result)  # still a matrix
# [1] "matrix"
dim(result)
# [1] 5 1

Even on the 1x1 matrix:

test3 = matrix(1)  # is a matrix
result3 = test3[1:1,,drop=F]
class(result3)
# [1] "matrix"
dim(result3)
# [1] 1 1

Maybe you've loaded other packages that are overriding the default behavior? What makes you think you don't end up with a matrix?

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • Hmmm, you are right. The codes do work after I restart Rstudio. I wonder what I ran caused this to happen. Let me experiment a bit and report back to the group. – dasf Jun 18 '18 at 01:44
  • Hey Gregor, I think we should reopen this one, would you take a look? – Aaron left Stack Overflow Jun 18 '18 at 16:19
  • @Aaron I disagree. Assigning variables over `T` or `F` is a common problem. Having `drop = F` not work because of that is a very specific system. If anything, I'd mark it as a duplicate of the already-linked "Is there anything wrong with using T & F instead of TRUE & FALSE?" question. What benefit do you see in re-opening the question? – Gregor Thomas Jun 18 '18 at 16:23
  • It may be a common problem, but it's not an obvious answer (as seen by the answers before mine and the rush to close). I think for future readers that may have this problem, having a question that specifically answers it is valuable. Marking as a dup might work, but really, it's a duplicate answer but not a duplicate question. It's certainly no longer off-topic because it can't be reproduced, though. – Aaron left Stack Overflow Jun 18 '18 at 16:31
  • Would you also create q/a pairs for "Why does `na.rm = T` not work with `mean`?" "Why does `stringsAsFactors = F"` not work?", etc.? There has to be some level of generalizability with this issue or it is absurd, which is why marking as a dupe seems appropriate to me. I don't think the above Q is an **ideal** dupe target, but maybe something focused on the general issue, perhaps a new R-FAQ on "Why doesn't `T` and `F` work for `TRUE` and `FALSE`?" (if something like that doesn't yet exist). If you want to edit this into something general and OP is agreeable, I'd be happy with that solution. – Gregor Thomas Jun 18 '18 at 16:43
  • @Aaron see also [this question](https://stackoverflow.com/q/40244112/903061) where the dupe approach was taken, and I'm sure there are more that are not linked. It would be nice to have a canonical dupe for the issue. Another option would be to ask/answer a new question created for that purpose. – Gregor Thomas Jun 18 '18 at 16:49
  • Well, closed as dupe would be better than closed as off-topic. Can non-moderators do that, or do we need to flag it? I think the linked question would be appropriate for this one too, it seems pretty canonical already. Generally I'm in the SO camp that doesn't mind similar questions and leans against closing and/or duping, though we're definitely outnumbered in the active SO crowd, alas... – Aaron left Stack Overflow Jun 18 '18 at 20:44
  • A mod could presumably do it instantly. I added a reopen vote (we're up to 2) but it would take 5 total.I have enough rep that I can close as a dupe by myself, but that may not work after a reopen. You could flag a mod and make the recommendation. – Gregor Thomas Jun 18 '18 at 20:47
0

The following works:

test <- matrix(test[5:1,, drop = F], nrow = 5, ncol = 1)

When you use is.matrix to test it, the output is a matrix. At the same time, you specify the number of rows (nrow) and number of columns (ncol) to coerce it to the number of rows and columns you require.

DTYK
  • 1,098
  • 1
  • 8
  • 33
  • But as matrix would turn a 1-row 2-col matrix into a 2-row 1-col matrix. I need something that can preserve the original dimensions. – dasf Jun 18 '18 at 01:22
  • @dasf I have edited my answer. Does it answer your question? The result is a matrix, and the rows and columns of the resulting matrix can be prespecified based on what you require (e.g. 5 rows and 1 columns). – DTYK Jun 18 '18 at 01:27
  • 1
    Seems unnecessarily complicated... – Gregor Thomas Jun 18 '18 at 01:36
  • OK that could work, though I have to find out how many rows and cols the matrix has. I just realized I could coerce the reordered non-matrix into the dimensions of the original matrix by doing something like `dim(new) = dim(old)`. – dasf Jun 18 '18 at 01:37
  • @Gregor I added in the rows and columns as the topic starter requested it and, yes, your answer works too and it is more succinct. – DTYK Jun 18 '18 at 01:38