在 R 中:子集或 dplyr::filter 带有向量中的变量
In R: subset or dplyr::filter with variable from vector
df <-
data.frame(a=LETTERS[1:4],
b=rnorm(4)
)
vals <- c("B","D")
我可以 filter/subset df
使用 val
中的值:
dplyr::filter(df, a %in% vals)
subset(df, a %in% vals)
两者都给出:
a b
2 B 0.4481627
4 D 0.2916513
如果我在向量中有一个变量名怎么办,例如:
> names(df)[1]
[1] "a"
然后它不起作用 - 我猜是因为它被引用了
dplyr::filter(df, names(df)[1] %in% vals)
[1] a b
<0 rows> (or 0-length row.names)
你是怎么做到的?
更新(如果是 dplyr::tbl_df(df) 会怎样)
下面的答案适用于 data.frames,但不适用于 dplyr::tbl_df 包装数据:
df<-dplyr::tbl_df(df)
dplyr::filter(df, df[,names(df)[1]] %in% vals)
不起作用(我认为 tbl_df
是 df 之上的简单包装?)
这再次起作用:
dplyr::filter(df, as.data.frame(df)[,names(df)[1]] %in% vals)
最终更新:它与 tbl_df() 一起使用 lazyeval::interp
请参阅下面 AndreyAkinshin 的解决方案。
您可以使用 df[,"a"]
或 df[,1]
:
df <- data.frame(a = LETTERS[1:4], b = rnorm(4))
vals <- c("B","D")
dplyr::filter(df, df[,1] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
subset(df, df[,1] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
dplyr::filter(df, df[,"a"] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
subset(df, df[,"a"] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
使用 dplyr::tbl_df(df)
lazyeval::interp
的一些魔法可以帮助我们!
df <- dplyr::tbl_df(df)
expr <- lazyeval::interp(quote(x %in% y), x = as.name(names(df)[1]), y = vals)
df %>% filter_(expr)
# Source: local data frame [2 x 2]
#
# a b
# 1 B 0.4481627
# 2 D 0.2916513
在 tidyverse 中解决这个问题的简单方法:
library(tidyverse)
df <- data.frame(a = LETTERS[1:4], b = rnorm(4))
vals <- c("B","D")
df %>% filter(!!sym(names(.)[1]) %in% vals)
您可以使用 .data
代词来 select 列名称 -
library(dplyr)
col <- names(df)[1]
df %>% filter(.data[[col]] %in% vals)
# a b
# <chr> <dbl>
#1 B -1.06
#2 D -1.75
或以 R 为基数 -
df[df[[col]] %in% vals, ]
df <-
data.frame(a=LETTERS[1:4],
b=rnorm(4)
)
vals <- c("B","D")
我可以 filter/subset df
使用 val
中的值:
dplyr::filter(df, a %in% vals)
subset(df, a %in% vals)
两者都给出:
a b
2 B 0.4481627
4 D 0.2916513
如果我在向量中有一个变量名怎么办,例如:
> names(df)[1]
[1] "a"
然后它不起作用 - 我猜是因为它被引用了
dplyr::filter(df, names(df)[1] %in% vals)
[1] a b
<0 rows> (or 0-length row.names)
你是怎么做到的?
更新(如果是 dplyr::tbl_df(df) 会怎样)
下面的答案适用于 data.frames,但不适用于 dplyr::tbl_df 包装数据:
df<-dplyr::tbl_df(df)
dplyr::filter(df, df[,names(df)[1]] %in% vals)
不起作用(我认为 tbl_df
是 df 之上的简单包装?)
这再次起作用:
dplyr::filter(df, as.data.frame(df)[,names(df)[1]] %in% vals)
最终更新:它与 tbl_df() 一起使用 lazyeval::interp
请参阅下面 AndreyAkinshin 的解决方案。
您可以使用 df[,"a"]
或 df[,1]
:
df <- data.frame(a = LETTERS[1:4], b = rnorm(4))
vals <- c("B","D")
dplyr::filter(df, df[,1] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
subset(df, df[,1] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
dplyr::filter(df, df[,"a"] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
subset(df, df[,"a"] %in% vals)
# a b
# 2 B 0.4481627
# 4 D 0.2916513
使用 dplyr::tbl_df(df)
lazyeval::interp
的一些魔法可以帮助我们!
df <- dplyr::tbl_df(df)
expr <- lazyeval::interp(quote(x %in% y), x = as.name(names(df)[1]), y = vals)
df %>% filter_(expr)
# Source: local data frame [2 x 2]
#
# a b
# 1 B 0.4481627
# 2 D 0.2916513
在 tidyverse 中解决这个问题的简单方法:
library(tidyverse)
df <- data.frame(a = LETTERS[1:4], b = rnorm(4))
vals <- c("B","D")
df %>% filter(!!sym(names(.)[1]) %in% vals)
您可以使用 .data
代词来 select 列名称 -
library(dplyr)
col <- names(df)[1]
df %>% filter(.data[[col]] %in% vals)
# a b
# <chr> <dbl>
#1 B -1.06
#2 D -1.75
或以 R 为基数 -
df[df[[col]] %in% vals, ]