在自定义 dplyr 函数中使用列向量

问题描述 投票:0回答:1

我正在尝试使用 tidyverse 创建一个函数,该函数允许我获取列名向量(类因子),计算有多少观察值满足特定条件(值 ==“是”),

mutate()
和使用此总和创建新列,以便稍后汇总数据。

我已经编写了一个可以为单个列执行此操作的函数,但我希望能够使用

all_of()
语法将任意长度的列名称向量传递给该函数。当我尝试这个时,我得到一个与向量同名的新列(包括我的
_count
后缀)而不是向量中的值。

这类似于 TimTeaFan 的帖子 但我想传递一个长度 > 1 的向量。

我想我可能需要在 dplyr 和更多 rlang 中使用 (. . .) 选项,但我还没有找到正确的组合。由于 NSE,当我将 (...) 替换为 objective 时,该功能不起作用。我也尝试过

rlang::as_name()
rlang::get_env()
的变体。有一个过时的工作簿也使用了
purrr::map()
,但我在这里实施它没有任何运气。

我要么得到错误:找不到列

x
。 或错误:Promise 已被强制

这是一个可重现的数据示例

dat <- tibble(category = rep(letters[1:10], 2),
              intake = factor(c(rep("no", 12), rep("yes", 8))), 
              outtake = factor(c(rep("yes", 11), rep("no", 9))),
              pretake = factor(c(rep(c("no", "yes"), 10))))

yessum <- function(.data, objective) {
  .data %>%
    dplyr::mutate("{{objective}}_count" := sum(
      ifelse(
        unlist(!!rlang::ensym(objective)) == "yes", 1, 0)))
}

dat %>%
  group_by(category) %>%
  yessum(intake)

我希望能够将某些列名的向量传递给 yessum 并接收一组新列,就像

intake_new
但名为
outtake_new
pretake_new
.

这是我尝试时目前发生的事情:

vars <- c("intake", "outtake", "pretake")

dat %>%
  group_by(category) %>%
  yessum(vars)

欢迎任何帮助!

r dplyr purrr rlang
1个回答
1
投票

您不一定需要该功能,因为您只需

mutate
across
列并获得每个类别的总和。

library(tidyverse)

dat %>%
  group_by(category) %>%
  mutate(across(ends_with("take"), .fns = list(count = ~sum(. == "yes"))))

或者如果你有一个长列表,那么你可以直接在

vars
语句中使用
across

vars <- c("intake", "outtake", "pretake")

dat %>%
  group_by(category) %>%
  mutate(across(vars, .fns = list(count = ~sum(. == "yes"))))

输出

  category intake outtake pretake intake_count outtake_count pretake_count
   <chr>    <fct>  <fct>   <fct>          <int>         <int>         <int>
 1 a        no     yes     no                 0             2             0
 2 b        no     yes     yes                0             1             2
 3 c        no     yes     no                 1             1             0
 4 d        no     yes     yes                1             1             2
 5 e        no     yes     no                 1             1             0
 6 f        no     yes     yes                1             1             2
 7 g        no     yes     no                 1             1             0
 8 h        no     yes     yes                1             1             2
 9 i        no     yes     no                 1             1             0
10 j        no     yes     yes                1             1             2
11 a        no     yes     no                 0             2             0
12 b        no     no      yes                0             1             2
13 c        yes    no      no                 1             1             0
14 d        yes    no      yes                1             1             2
15 e        yes    no      no                 1             1             0
16 f        yes    no      yes                1             1             2
17 g        yes    no      no                 1             1             0
18 h        yes    no      yes                1             1             2
19 i        yes    no      no                 1             1             0
20 j        yes    no      yes                1             1             2
© www.soinside.com 2019 - 2024. All rights reserved.