R中tidyverse编程中的变量屏蔽

variable masking in tidyverse programming in R

很难在 函数 中重用代码。我用 [[ 子集 .data 但是收到拼接错误。我在下面的 tidy 函数中提供了一个示例和一个使用“if”语句的解决方案。是否可以在 tidyverse 编程中使用变量掩码?

数据框

set.seed(123)
(df=data.frame(
  Yrs_Before=sample(1:8, 3),
  Yrs_After=sample(1:8, 3),
  Before.Yr_1=sample(1:8, 3),
  Before.Yr_2=sample(1:8, 3),
  Before.Yr_3=sample(1:8, 3),
  Before.Yr_4=sample(1:8, 3),
  Before.Yr_5=sample(1:8, 3),
  Before.Yr_6=sample(1:8, 3),
  Before.Yr_7=sample(1:8, 3),
  Before.Yr_8=sample(1:8, 3),
  After.Yr_1=sample(1:8, 3),
  After.Yr_2=sample(1:8, 3),
  After.Yr_3=sample(1:8, 3),
  After.Yr_4=sample(1:8, 3),
  After.Yr_5=sample(1:8, 3),
  After.Yr_6=sample(1:8, 3),
  After.Yr_7=sample(1:8, 3),
  After.Yr_8=sample(1:8, 3)
  
))

是否可以为以下函数使用变量掩码?

sums=function(data,crashes,yrs){
  data %>%
    dplyr::rowwise() %>%
    dplyr::transmute(sum = cumsum(c_across(matches(.data[[crashes]])))[.data[[yrs]]])
}

但是收到错误。


sums(df,"After.Yr")
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named,  : 
                           argument "yrs" is missing, with no default
                         Called from: splice(dot_call(capture_dots, frame_env = frame_env, named = named, 
                                                      ignore_empty = ignore_empty, unquote_names = unquote_names, 
                                                      homonyms = homonyms, check_assign = check_assign))

与在相应的“一年前”期间发生的计数类似(例如“Before.Yr”)。

sums(df,"Before.Yr")
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named,  : 
  argument "yrs" is missing, with no default
Called from: splice(dot_call(capture_dots, frame_env = frame_env, named = named, 
    ignore_empty = ignore_empty, unquote_names = unquote_names, 
    homonyms = homonyms, check_assign = check_assign))

以下是使用“if”语句完成的,它提供了所需的结果。下面提供了“之前”(Before.Yr) 和“之后”(After.Yr) 时期

所需的结果

sums = function(data,counts){
  data %>%
    dplyr::rowwise() %>%
    dplyr::transmute(sums = if(counts=="Before.Yr") {cumsum(c_across(matches('Before.Yr')))[Yrs_Before]} else{cumsum(c_across(matches('After.Yr')))[Yrs_After]})}


在后期使用崩溃。

sums(df,"After.Yr")
# A tibble: 3 × 1
# Rowwise: 
sums
<int>
  1    21
2    20
3     6

使用前一段时间的崩溃。

> sums(df,"Before.Yr")
# A tibble: 3 × 1
# Rowwise: 
sums
<int>
  1    23
2    33
3    11

而不是使用 matches(.data[[crashes]]) 简单地做 matches(crashes) 当然你必须为 yrs 传递一个列名:

library(dplyr)

sums <- function(data, crashes, yrs) {
  data %>%
    dplyr::rowwise() %>%
    dplyr::transmute(sum = cumsum(c_across(matches(crashes)))[.data[[yrs]]])
}

sums(df, "After.Yr", "Yrs_After")
#> # A tibble: 3 × 1
#> # Rowwise: 
#>     sum
#>   <int>
#> 1    21
#> 2    20
#> 3     6


sums(df, "Before.Yr", "Yrs_Before")
#> # A tibble: 3 × 1
#> # Rowwise: 
#>     sum
#>   <int>
#> 1    23
#> 2    33
#> 3    11