将屏蔽变量在“...”中传递给 group_by() 示例 1示例 2示例 3示例 4

如何解决将屏蔽变量在“...”中传递给 group_by() 示例 1示例 2示例 3示例 4

动机

我正在创建一个自定义实用程序函数 streak_over(),其目的是在语法上模仿 dplyr 动词 group_by()。虽然 streak_over() 本质上包装了 group_by() 的分组功能,但这种分组是进一步操作的前兆。

在给定数据集的上下文中,streak_over() 的目的是为共享一个组的 连续 观察的每个“条纹”建立索引,其中预先建立了分组(通过先验 { {1}}) 或在 group_by() 本身中指定(通过 tidy evaluation)。

这是一个说明,其中分组变量分别为 streak_over()x

y

详情

除了一个小问题外,我的所有工作都完全按预期工作。这是 x y group_id streak_index <dbl> <chr> <int> <int> 1 1 a 1 1 2 1 a 1 1 3 2 b 4 2 4 2 b 4 2 5 1 a 1 3 6 2 a 3 4 7 1 b 2 5 8 2 b 4 6 的一般形式,它在 streak_over 中接受 ... 的所有参数,然后返回一个 group_by() 向量(如 integer)连胜指数。 注意: streak_index.start 是我自己定义的参数,用于定义“连续”的标准;除了它们作为函数头中的命名参数存在之外,它们与我的问题无关。

.min

一般来说,可用性是理想的。给定一个 streak_over <- function(...,.start = 1,.min = 2) { return( dplyr::group_by(...) # %>% # ... %>% Further Operations %>% ... ) } data.frame | x 来自上图

y

我们可以通过符合人体工程学的工作流程生成我们的条纹指数向量:

df <- data.frame(x = c(1,1,2,2),y = c("a","a","b","b"))

我们也可以像连续使用 df %>% group_by(x,y) %>% streak_over(.add = TRUE) # [1] 1 1 2 2 3 4 5 6 df %>% group_by(x) %>% streak_over(y,.add = TRUE) # [1] 1 1 2 2 3 4 5 6 df %>% streak_over(x,y) # [1] 1 1 2 2 3 4 5 6 一样更改分组:

group_by()

最后,我们可以生成没有任何分组的索引:

df %>% group_by(x) %>% streak_over(y,.add = FALSE)
# [1] 1 1 2 2 3 3 4 4

df %>% group_by(x) %>% streak_over(y)  # .add = FALSE by default
# [1] 1 1 2 2 3 3 4 4

df %>% streak_over(y)
# [1] 1 1 2 2 3 3 4 4

但是,我想更改一种默认行为。

问题

根据它包装的 df %>% streak_over() # no grouping given # [1] 1 1 1 1 1 1 1 1 函数的当前默认值 (.add = FALSE),当 group_by() 未另行指定时,streak_over() 当前会覆盖现有分组。虽然我通常确实喜欢这种行为,但在一种情况下,它违反直觉且不方便

.add

这里已经存在一个分组并且可能很有用。此外,df %>% group_by(x,y) %>% streak_over() # [1] 1 1 1 1 1 1 1 1 不包含进一步的分组变量,否则需要通过 streak_over() 进行消歧。 在这种特殊情况下,只需.add 保留现有分组会非常方便,而所有其他默认设置都遵循streak_over()

group_by()

这里列出了我想要的行为:

df %>% group_by(x,y) %>% streak_over() # [1] 1 1 2 2 3 4 5 6 .add 调用中指定的分组变量 未指定分组变量
(缺失) streak_over() 的当前默认行为 始终添加到现有分组
group_by() 添加到现有分组 添加到现有分组
TRUE 覆盖现有分组 覆盖现有分组

我还希望这种“延迟”是动态的:如果 R 团队使用新的默认设置(如 FALSE)更新 dplyr::group_by(),我希望 {{1} } 以与 mutate(.add = TRUE, 工作流程保持一致,而不是使用可能过时的硬编码默认值(如 streak_over())。

最后,为了美观和专业,我希望将 dplyr 的函数头保留为大致规范的形式:

streak_over(.add = TRUE,

尝试

都没有成功,我探索了很多方法。我当前的迭代

streak_over()

与许多其他人一样,由于似乎以下原因而失败:

  1. 尽管 this answer 支持我最初的直觉,但 streak_over <- function(...,.min = 2) { # ... } # Or... streak_over <- function(.data,...,.add,.drop,.min = 2) { # ... } 无法有效测试屏蔽变量的存在(例如 streak_over <- function(.data,.min = 2) { if(rlang::is_missing(.add) && !length(list(...))) { .add <- TRUE if(!rlang::is_empty(dplyr::group_vars(.data))) { message("Existing groups will be kept. Discard with '.add = FALSE'.") } } return( dplyr::group_by(.data,.add = rlang::maybe_missing(.add),.drop = rlang::maybe_missing(.drop)) # %>% # ... %>% Further Operations %>% ... ) } 中的 length(list(...))y) 中,而 df 似乎同样不可行。事实上,前一种方法给了我下面的错误;它似乎将 streak_over(y) 解释为自身的对象,而不仅仅是 match.call(expand.dots = FALSE) == match.call(expand.dots = TRUE) 中变量的符号
y
  1. 似乎 .datarlang::maybe_missing() 的搭配效果不佳,其值应该模拟缺失的参数。由于 df %>% group_by(x) %>% streak_over(y) # Error in streak_over(.,y) : object 'y' not found 无条件地将 dplyr 强制转换为 group_by(),因此我收到以下错误:
.add
logical
  1. 即使我试图折叠函数头 (streak_over <- function(.data,.min = 2) { # Condition REMOVED to progress beyond error above. return( dplyr::group_by(.data,.drop = rlang::maybe_missing(.drop)) # %>% # ... %>% Further Operations %>% ... ) } ),并让 df %>% group_by(x) %>% streak_over(y) # Error in if (.add) { : argument is not interpretable as logical “潜伏在阴影中”直到它被明确指定 (streak_over(...,.min = 2)),我也不得不改变它的值以某种方式:有条件地.add,然后是streak_over(.add = TRUE,。不幸的是,如果用户确实明确指定了 new_add <- TRUE,R 会将它包含在 group_by(...,.add = new_add) 旁边的 .add 中,并且无法通过分配 {{ 1}} 在适当的地方。结果是(公认可预测的)错误:
...
.add = new_add

结论

我觉得必须有条件地将形式参数的默认值覆盖为包装函数的方法,即使它是包含掩码或整齐计算的神秘 new_add <- NULL变量。然而,我怀疑这接近于 streak_over <- function(...,.min = 2) { # Check if '.add' is present in '...'; and if no masked variables are present therein. if(is.null(list(...)$.add) && all(names(list(...)) %in% c(".data",".add",".drop"))) { new_add <- TRUE } else { new_add <- NULL } return( dplyr::group_by(...,.add = new_add) # %>% # ... %>% Further Operations %>% ... ) } 领域,这是我绝对缺乏经验的 R 领域。

一如既往,感谢您的考虑以及您可能提供的任何帮助。


更新

感谢来自 hintktiu,在 Stack Overflow 上与 further research 合成,我拼凑了一个有点“hacky”的解决方案,它似乎满足了我最初的标准:>

df %>% group_by(x,y) %>% streak_over(.add = FALSE)
# Error in dplyr::group_by(...,.add = add) : 
#  formal argument ".add" matched by multiple actual arguments

我欢迎任何进一步的帮助:

  • 提供更优雅的解决方案;可能(说)如建议的 heredefault 包,如果安全实施,这看起来理想的手术......尽管我确实想知道掩码将正确翻译。 不幸的是,我的第一次尝试失败了:虽然一切看起来都很干净
...

并且打印输出表明对于本地 symbolstreak_over <- function(.data,.min = 2) { # Store the defaults for 'group_by()',in case they are needed. gb_formals <- formals(dplyr::group_by) # If neither '.add' nor masked variables in '...' were supplied to # 'streak_over()',yet a grouping already exists in '.data',override the # 'group_by()' default to intuitively preserve the grouping. if(rlang::is_missing(.add) && !length(rlang::enquos(...)) && !rlang::is_empty(dplyr::group_vars(.data))) { .add <- TRUE message("Existing groups will be kept. Discard with '.add = FALSE'.") } return( dplyr::group_by(.data,.add = rlang::maybe_missing(.add,gb_formals$.add),.drop = rlang::maybe_missing(.drop,gb_formals$.drop)) # %>% # ... %>% Further Operations %>% ... ) } 现在默认为 streak_over <- function(...,.min = 2) { # Condition always TRUE here to illustrate the point. if(TRUE) { default::default(group_by) <- list(.add = TRUE) } # Print out default,to check if correctly updated. default::default(group_by) return( group_by(...) # %>% # ... %>% Further Operations %>% ... ) } ,输出仍然表现为 .add

TRUE
  • 改进我现有解决方案的技术(工具、结构、语法等);可能(比如)使用 group_by() 而不是 .add = FALSE
  • 稳定此解决方案的功能;特别是对 df %>% group_by(x,y) %>% streak_over() # - .data = [none] # - ... = [none] # * - .add = TRUE # - .drop = group_by_drop_default(.data) # [1] 1 1 1 1 1 1 1 1 的结构变化更加稳健,包括但不限于:
    • 更改 rlang::fn_fmls() 中参数的现有默认值
    • 为之前没有默认值的 base::formals() 中的参数添加默认值
    • dplyr::group_by() 中现有参数的重命名
    • group_by() 添加新参数。

除了满足原始标准的答案外,任何成功提供进一步帮助(同时满足原始标准)的答案都将收到我的赞成票和接受考虑。

奖金

我也很好奇以下哪个 group_by() 标头更规范:

  • group_by():典型的包装器。
  • group_by()suggestedktiu
  • streak_over():类似于streak_over(...,.min = 2)

请注意,此函数旨在模仿 streak_over(...,.min = 2) 语法,模仿 streak_over(.data,.min = 2)。然而,在执行进一步的操作之前,dplyr 仍然包装另一个函数:在这种情况下,R 绝大多数将传递给包装函数的所有参数表示为包装头中的 dplyr。再说一次,出于纯粹的功能目的,group_by(.data,.drop) 是传递给 streak_over() 的唯一形式参数,它需要在 ... 标头中的 .add 之外显式存在。

在权威参考资料的支持下,明确这一点可能会成为接受答案的“决胜局”。

再次感谢! — 格雷格

解决方法

这是一种方法

  1. 使用 rlang::enquos() 来解除 ... 中的函数参数,
  2. 在以下情况下提供.add = TRUE
    • .add 未明确传递 AND
    • ... 仅包含一个“非特殊点”参数(数据的名称,或管道中的 .
  3. 使用这些变量调用 group_by() 的自定义包装器:
streak_over <- function(...,.start = 1,.min = 2) {
  defused <- rlang::enquos(...)
  if (any(".add" %in% names(defused),sum(! grepl("\\..+",names(defused))) > 1))
    custom_wrapper(...)
  else
    custom_wrapper(...,.add = TRUE)
}

custom_wrapper <- function(...) {
  # add custom logic here
  dplyr::group_by(...)
}

请注意,我并没有特意匹配您指定的所有案例,但这可能是一个概念证明,您可以将其推向更成熟的解决方案。

尝试一下:

示例 1

library(dplyr)

df %>%
   group_by(x) %>%
   streak_over()

保持分组:

# A tibble: 8 x 2
# Groups:   x [2]
      x y    
  <dbl> <chr>
1     1 a    
2     1 a    
3     2 b    
4     2 b    
5     1 a    
6     2 a    
7     1 b    
8     2 b    

示例 2

df %>%
  group_by(x) %>%
  streak_over(y)

覆盖分组:

# A tibble: 8 x 2
# Groups:   y [2]
      x y    
  <dbl> <chr>
1     1 a    
2     1 a    
3     2 b    
4     2 b    
5     1 a    
6     2 a    
7     1 b    
8     2 b    

示例 3

df %>%
   group_by(x) %>%
   streak_over(.add = F)

删除分组:

# A tibble: 8 x 2
      x y    
  <dbl> <chr>
1     1 a    
2     1 a    
3     2 b    
4     2 b    
5     1 a    
6     2 a    
7     1 b    
8     2 b    

示例 4

df %>%
  group_by(x) %>%
  streak_over(y,.add = T)

添加分组:

# A tibble: 8 x 2
# Groups:   x,y [4]
      x y    
  <dbl> <chr>
1     1 a    
2     1 a    
3     2 b    
4     2 b    
5     1 a    
6     2 a    
7     1 b    
8     2 b    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res