在R中选择列的规范方法

3
我正在比较dplyr和"纯R"中常见的“整理”操作(请参见此处的输出此处的源代码,以了解我的意思)。
我很难找到一种“规范”且简洁的方法,只使用变量名来选择列(所谓的规范,指的是纯粹的R语言,并且容易为任何具有最基本的R语言理解的人所理解(因此不包括“巫术技巧”))。
例如:
## subset: all columns from "var_1" to "var_2" excluding "var_3"

## dplyr: 
table %>% select(var_1:var_2, -var_3)

## plain R: 
r <- sapply(c("var_1", "var_2", "var_3"), function(x) which(names(table)==x))
table[ ,setdiff(r[1]:r[2],r[3]) ]

任何改进基本R语法的建议吗?
编辑
我实施了一些建议,并比较了不同语法的性能,发现使用match和subset会导致性能惊人的下降:
# plain R, v1
system.time(for (i in 1:100) { 
    r <- sapply(c("size", "country"), function(x) which(names(cran_df)==x))
    cran_df[,r[1]:r[2]] } )
##    user  system elapsed 
##   0.006   0.000   0.007

# plain R, using match
system.time(for (i in 1:100) { 
    r <- match(c("size", "country"), names(cran_df))
    cran_df[,r[1]:r[2]] %>% head(n=3) } )
##    user  system elapsed 
##   0.056   0.028   0.084

# plain R, using match and subset
system.time(for (i in 1:100) {
    r <- match(c("size", "country"), names(cran_df))
    subset(cran_df, select=r[1]:r[2]) %>% head(n=3) } )
##    user  system elapsed 
##  11.556   1.057  12.640

# dplyr
system.time(for (i in 1:100) select(cran_tbl_df,size:country))
##    user  system elapsed 
##   0.034   0.000   0.034

看起来 subset 的实现不够优化...


3
使用grep函数查找包含'var_1'、'var_2'或'var_3'的字符串时,您可以使用表达式'var_[12]'来更简洁地完成。这种方法被认为是一种常规技巧,而不是一种黑魔法。 - rawr
4
请注意,r <- 行可以替换为 r <- match(c("var_1", "var_2", "var_3"), names(table)) - David Robinson
我不理解你的第三个测试:为什么要同时使用matchsubset?为什么不直接使用subset(cran_df, select=size:country)呢? - David Robinson
话虽如此,你对大型数据框的性能影响完全正确(在小型数据框上,“subset”实际上比“select”更快)。首先,看一下代码“base::subset.data.frame”:如果第二个参数缺失(即子集行),它只是创建一个向量“rep_len(TRUE, nrow(x))”,并使用该向量来子集行:这是一种浪费操作,因为我们只是查看列。 - David Robinson
@DavidRobinson:关于match和subset,我不知道可以这样做(懒得看subset的手册),我会修改的。 - Alexandre Halm
显示剩余2条评论
1个回答

8
您可以使用内置的subset函数,它可以接受一个select参数,其语法类似于dplyr::select(尽管不完全相同)。请注意,删除列必须在第二步完成:
t1 <- subset(table, select = var1:var2)
t2 <- subset(t1, select = -var_3)

或者:

subset(subset(table, select = var1:var2), select = -var_3)

例如:

subset(subset(mtcars, select = c(mpg:wt)), select = -hp)

谢谢,我会尝试的 - 这可能是在普通R中最好的了。 - Alexandre Halm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接