The "select helper" functions appear to be a bit too aggressive about excluding everything before it. This may be a documentation thing, but I expect positive helper functions to be additive (which appears to be the case), and "none-found" helper functions to not be subtractive.
Note: in all examples, I'm using summarize_at (and mean) primarily for terse output. The behavior is the same with other helpers (e.g., matches, starts_with) and within other verbs (e.g., select, mutate_at).
Currently-Correct Behavior
For the record, "all matches found" works fine, as does a not-found match when it is the first one:
### expecting am, gear, vs summarize_at(mtcars, vars(contains("am"), contains("gear"), contains("vs")), funs(mean)) # am gear vs # 1 0.40625 3.6875 0.4375 ### expecting gear, vs summarize_at(mtcars, vars(contains("FOO"), contains("gear"), contains("vs")), funs(mean)) # gear vs # 1 3.6875 0.4375
Expected Behavior
I have been interpreting select(mtcars, contains("am"), contains("foo")) to return all columns that contain "am" or "foo", regardless of the order I provide the calls to contains (and other helpers).
Errant Behavior
Everything before a failing conditional is dropped, regardless of match:
### expecting am, gear summarize_at(mtcars, vars(contains("am"), contains("gear"), contains("FOO")), funs(mean)) # data frame with 0 columns and 0 rows ### expecting am, vs summarize_at(mtcars, vars(contains("am"), contains("FOO"), contains("vs")), funs(mean)) # vs # 1 0.4375
This appears to be because the helper functions, when nothing is found, return the negative vector of column indices:
contains("a", vars = colnames(mtcars)) # [1] 5 9 10 11 contains("FOO", vars = colnames(mtcars)) # [1] -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11