开发者

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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜