R - brevity when subsetting?
I'm still new to R and do all of my subsetting via the pattern:
data[ command that produces logical with same length as data ] or subset( data , command that produces logical with same length as data )for e开发者_C百科xample:
test = c("A", "B","C")
ignore = c("B")
result = test[ !( test %in% ignore ) ]
result = subset( test , !( test %in% ignore ) )
But I vaguely remember from my readings that there's a shorter/(more readable?) way to do this? Perhaps using the "with" function?
Can someone list alternative to the example above to help me understand the options in subsetting?
I don't know of a more succinct way of subsetting for your specific example, using only vectors. What you may be thinking of, regarding with
, is subsetting data frames based on conditions using columns from that data frame. For example:
dat <- data.frame(variable1 = runif(10), variable2 = letters[1:10])
If we want grab a subset of dat
based on a condition using variable1
we could do this:
dat[dat$variable1 < 0,]
or we can save ourselves having to write dat$*
each time by using with
:
with(dat,dat[variable1 < 0,])
Now, you'll notice that I really didn't save any keystrokes by doing that in this case. But if you have a data frame with a long name, and a complicated condition it can save you a bit. See also the related ?within
command if you're altering the data frame in question.
Alternatively, you can use subset
which can do essentially the same thing:
subset(dat, variable1 < 0)
subset
can also handle conditions on the columns via the select argument.
The with
function would help if test were a column in a data frame (or object in a list), but with global vectors with does not help.
Some people have created a not in operator that could save a couple of key strokes from what you did. If all the values in test are unique then the setdiff
function may be what you are thinking of (but if for example you had multiple "A"
s then setdiff
would only return 1 of them).
With your ignore being only 1 value you could use test != ignore
, but that does not generalize to ignore having 2 or more values.
I have seen timed comparisons of alternate methods and %in% (based on match) was one of the best performing strategies.
Alternates:
test[!test=="B"] #logical indexing
test[which(test != "B")] #numeric indexing
# the which() is not superfluous when there are NA's if you want them ignored
Another alternative to the original example:
test[test != ignore]
Other ways, using joran's example:
set.seed(1)
df <- data.frame(variable1 = runif(10), variable2 = letters[1:10])
Returning one column: df[[1]]
. df$name is equivalent to df[["name", exact = FALSE]]
df[df[[1]] < 0.5, ]
df[df["variable1"] < 0.5, ]
Returning one data frame of one column: df[1]
df[df[1] < 0.5, ]
Using with
with(df, df[df[[1]] < 0.5, ]) # One column
with(df, df[df["variable1"] < 0.5, ]) # One column
with(df, df[df[1] < 0.5, ]) # data frame of one column
Using dplyr
:
library(dplyr)
filter(df, variable1 < 0.5)
精彩评论