2

I have a table containing filters, such as

> X = data.frame(filter1=c(1,1,1),filter2=c(1,1,0),filter3=c(1,0,0))
> X
  filter1 filter2 filter3
1       1       1       1
2       1       1       0
3       1       0       0

I like to select the filters based on conditionals:

> selected_filters = c(1:2)
> X[,paste0("filter",c(selected_filters))]
  filter1 filter2
1       1       1
2       1       1
3       1       0

However, if I have only one column selected, the data frame converts into a list

> selected_filters = c(2)
> X[,paste0("filter",c(selected_filters))]
[1] 1 1 0

How to select also only one column keeping the result as a data frame? Desired result would look like

  filter2
1       1
2       1
3       0
Heikki
  • 2,214
  • 19
  • 34
  • Part of the problem was actually to try to find the correct documentation, because it is not obvious that for the square bracket syntax `X[...]` one cannot look for help using syntax `?[]`. As @acrun points out in his answer, one should seek for help with syntax `?Extract`. – Heikki Apr 16 '19 at 06:42
  • 2
    We can get help as with any other function: `?"["` will take us to *Extract* manual. Similarly `?"+"` would take us to *Arithmetic*, etc. – zx8754 Apr 16 '19 at 06:44
  • 1
    Note that you can use `selected_filters` instead of `c(selected_filters)` in the solutions proposed. – LocoGris Apr 16 '19 at 06:48

2 Answers2

2

We need drop = FALSE

X[, paste0("filter",c(selected_filters)), drop = FALSE]
#   filter2
#1       1
#2       1
#3       0

If we look at ?Extract, the Usage shows

x[i, j, ... , drop = TRUE]

and in the description, it says

drop - For matrices and arrays. If TRUE the result is coerced to the lowest possible dimension (see the examples). This only works for extracting elements, not for the replacement. See drop for further details.


Note that subset behavior is different because it is by default drop = FALSE

subset(X, select = paste0("filter",c(selected_filters)))
akrun
  • 874,273
  • 37
  • 540
  • 662
2

You will get a data frame If you avoid the comma.

X[paste0("filter", c(selected_filters))]
#  filter2
#1       1
#2       1
#3       0

str(X[paste0("filter", c(selected_filters))])
'data.frame':   3 obs. of  1 variable:
 $ filter2: num  1 1 0

str(X[,paste0("filter", c(selected_filters))])
 num [1:3] 1 1 0
Sotos
  • 51,121
  • 6
  • 32
  • 66