2

I have a data.frame containing multiple columns made up of TRUE and FALSE logical answers, as so:

>` .    X1    X2    X3    X4    X5    X6    X7    X8
 [1,] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE
 [2,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
 [3,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [4,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [5,] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
 [6,] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
 [7,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
`

I am trying to pull out only the titles of the columns where TRUE exists. For example here, I would get X4, X6, X7 and X8 out, but all others excluded.

For context, TRUE indicates a cell is responding to stimuli at that particular time point. I only need to know if the cell responds at all (i.e. TRUE exists in the column at least once), not when the cell responds.

Thank you in advance for any help regarding this!

GameDroids
  • 5,584
  • 6
  • 40
  • 59
Kevin
  • 89
  • 1
  • 5

3 Answers3

2

Try:

colnames(M)[colSums(M) >= 1]

The colSums will sum the TRUE values, which can then be compared against a value of 1 to extract the column names.

Example:

M <- matrix(FALSE, nrow = 4, ncol = 5, dimnames = list(NULL, paste0("X", 1:5)))
M[cbind(c(1, 2, 3, 4), c(2, 2, 4, 5))] <- TRUE
M
#         X1    X2    X3    X4    X5
# [1,] FALSE  TRUE FALSE FALSE FALSE
# [2,] FALSE  TRUE FALSE FALSE FALSE
# [3,] FALSE FALSE FALSE  TRUE FALSE
# [4,] FALSE FALSE FALSE FALSE  TRUE
colnames(M)[colSums(M) >= 1]
# [1] "X2" "X4" "X5"

This approach would work whether you are dealing with a matrix or a data.frame.

A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
  • Thank-you! This works perfectly. And yes, I meant matrix, not data frame - I'm a biologist and still get the jargon a tad off sorry! – Kevin Nov 06 '14 at 13:22
0

Try:

> names(ddf)[sapply(ddf, any)]
[1] "X4" "X6" "X7" "X8"
rnso
  • 23,686
  • 25
  • 112
  • 234
0

For a matrix m, you can do some column indexing

> unique(colnames(m)[col(m)[m]])
[1] "X4" "X6" "X7" "X8"

Or you could use the as.factor argument in col

> unique(col(m, as.factor=TRUE)[m])
[1] X4 X6 X7 X8
Levels: X1 X2 X3 X4 X5 X6 X7 X8

Originally I thought that was a matrix, but now I see it might be a data frame. So here are two possible data frame methods for a data frame d

> names(Filter(length, Map(which, d)))
[1] "X4" "X6" "X7" "X8"

And another one. This one doesn't use a loop like the Map option above

> names(d)[intersect(seq(d), col(d)[unlist(d)])]
[1] "X4" "X6" "X7" "X8"
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245