根据与dplyr :: select兼容的类/类型选择列 [英] Select columns based on classes/types with compatibility for dplyr::select

查看:165
本文介绍了根据与dplyr :: select兼容的类/类型选择列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何定义一个选择帮助器,该选择器根据列的类/类型来选择列并且还与dplyr的体系结构兼容?

How do I define a select helper that selects columns based on their class/type and that is also compatible with dplyr's architecture?

我查看了 https://cran. r-project.org/web/packages/dplyr/vignettes/introduction.html dplyr::select_helpers的帮助,但找不到任何让我根据类/类型进行选择的内容

I've looked at https://cran.r-project.org/web/packages/dplyr/vignettes/introduction.html and the help for dplyr::select_helpers but didn't find anything that would allow me to select based on classes/types

引入一些变化的WRT类/类型:

Bring in some variation WRT classes/types:

dat <- mtcars
dat <- dat %>% mutate(
  mpg = as.character(mpg),
  wt = as.factor(wt),
  vs = as.character(vs)
)

简而言之,我想对R中的所有个可能的类/类型(及其组合)使用通用方法:

In short, I would like to make this a generic approach for all possible classes/types (and combinations of them) in R:

dat[ , sapply(dat, is.character)]
# mpg    wt vs
# 1    21  2.62  0
# 2    21 2.875  0
# 3  22.8  2.32  1
# 4  21.4 3.215  1

基于基于列类型的数据框中的子集变量我可以这样:

select_on_class <- function(.data, cls = "numeric") {
  dat[ , names(.data)[sapply(.data,
    function(vec, clss) class(vec) %in% clss, clss = cls)]]
}
dat %>% select_on_class(c("character", "factor"))
# mpg    wt vs
# 1    21  2.62  0
# 2    21 2.875  0
# 3  22.8  2.32  1
# 4  21.4 3.215  1

但是我希望能够在对dplyr::select的调用中使用它,所以我尝试了此操作:

But I would like to be able to use it in calls to dplyr::select, so I tried this:

has_class <- function(.data, cls = "numeric") {
  nms <- names(.data)[sapply(.data,
    function(vec, clss) class(vec) %in% clss, clss = cls)]
  sapply(nms, as.name)
}
dat %>% has_class(c("character", "factor"))
# $mpg
# mpg
# 
# $wt
# wt
# 
# $vs
# vs

问题是sapply(nms, as.name)返回一个list,并且不能很好地与select的内部配合使用(顺便说一句,我还不完全了解):

The problem is that sapply(nms, as.name) returns a list and that doesn't play nicely with the internals of select (which I don't completely understand yet, BTW):

dat %>% select(has_class(c("character", "factor")))
# Error: All select() inputs must resolve to integer column positions.
# The following do not:
#   *  has_class("character")

dat %>% select_(has_class(c("character", "factor")))
# Error in UseMethod("as.lazy") : 
#   no applicable method for 'as.lazy' applied to an object of class "list"


编辑

基于使用select_if的答案,我试图进行概括并陷入困境:


EDIT

Based on the answer using select_if I tried to generalize and got stuck:

has_class <- function(.data, cls) {
  sapply(.data, function(vec, clss) class(vec) %in% clss, clss = cls)
}
dat %>% has_class(c("character", "factor"))
# mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
# TRUE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE
dat %>% select_if(has_class, c("character", "factor"))
# Error in vapply(tbl, p, logical(1), ...) : values must be length 1,
# but FUN(X[[1]]) result is length 32

AFAIU,.predicate函数只需要返回一个逻辑向量(has_class可以做到),我可以通过...将其他参数传递给.predicate函数(我可以做到).那我还是哪里出问题了?

AFAIU, the .predicate functions just needs to return a logical vector (which has_class does) and I can pass additional arguments to the .predicate functions via ... (which I did). So where am I still going wrong?

推荐答案

我认为dplyr::select_if()可能正是您想要的.例如

I think dplyr::select_if() may be what you are looking for. For example

dat <- mtcars %>% 
       mutate(mpg = as.character(mpg),
              wt = as.character(wt),
              vs = as.character(vs)
       ) %>% 
       select_if(is.character)

这篇关于根据与dplyr :: select兼容的类/类型选择列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆