当前位置: 首页 > 知识库问答 >
问题:

从全局环境中调用函数,其中包含 dplyr::汇总或变异中的隐式数据帧变量(来自调用 env?)

钱华晖
2023-03-14

我想在全局环境中创建一个函数列表,并根据需要在调用中调用它们以突变或汇总,这样它就可以使dplyr代码不那么冗长。问题在于,函数必须使用在数据帧内定义的变量,而不是全局 env。这可能都与对象舀取有关,这对我来说有点棘手。

对于以下所有代码,请加载所需的库:

library(dplyr)
library(purrr)
library(rlang)

例如:使用mtcars数据集,我想group_bya变量,并使用以下三个函数

我可以在电话中定义它们,总结如下,这很好:

mtcars %>%
        group_by(carb) %>%
        summarise(any_vs_four_gears = any(vs == 1 & gear == 4),
                  any_am_high_hp = any(am == 1 & hp >170),
                  all_combined = all(any_vs_four_gears, any_am_high_hp))

# # A tibble: 6 × 4
carb any_vs_four_gears any_am_high_hp all_combined
<dbl> <lgl>             <lgl>          <lgl>
1     1 TRUE              FALSE          FALSE
2     2 TRUE              FALSE          FALSE
3     3 FALSE             FALSE          FALSE
4     4 TRUE              TRUE           TRUE
5     6 FALSE             TRUE           FALSE
6     8 FALSE             TRUE           FALSE

我还可以将函数定义为表达式,然后计算调用中的表达式以进行总结,如下所示:

expressions_as_strings <- list(any_vs_four_gears = 'any(vs == 1 & gear == 4)',
                               any_am_high_hp = 'any(am == 1 & hp >170)',
                               all_combined = 'all(any_vs_four_gears, any_am_high_hp)')
expressions <- map(expressions_as_strings, parse_expr)

mtcars %>%
        group_by(carb) %>%
        summarise(any_vs_four_gears = !!expressions$any_vs_four_gears,
                  any_am_high_hp = !!expressions$any_am_high_hp,
                  all_combined = !!expressions$all_combined)

但是,我觉得如果我可以定义函数而不是表达式,我可以获得更大的灵活性。

我尝试了几种方法都没有成功:

方法1

method_1 <- list(any_vs_four_gears = function() any(vs == 1 & gear == 4),
                  any_am_high_hp = function() any(am == 1 & hp >170),
                  all_combined = function() all(any_vs_four_gears, any_am_high_hp))
#example

mtcars %>%
        group_by(carb) %>%
        summarise(any_vs_four_gears = method_1$any_vs_four_gears())

method_1失败。我认为这是因为函数从全局env中获取vs和gear的值,而不是数据。

方法

method_2 <- list(any_vs_four_gears = function(var1, var2) {any({{var1}} == 1 & {{var2}} == 4)},
                any_am_high_hp = function(var1, var2) {any({{var1}} == 1 & {{var2}} > 170)},
                all_combined = function(var1, var2) {all({{var1}}, {{var2}})})

# example

mtcars %>%
        group_by(carb) %>%
        summarise(any_vs_four_gears = method_2$any_vs_four_gears(vs, gear))

方法2确实有效,但是我必须包含变量作为函数的参数,我希望能够绕过它。

主要问题

有没有办法创建一个函数,该函数使用数据帧中的变量,但不需要将变量名称作为参数包含?我想要的是类似于method_1的东西,带有伪代码:

mtcars %>%
        group_by(carb) %>%
        summarise(any_vs_four_gears = method_x$any_vs_four_gears(),
                  any_am_high_hp = method_x$any_am_high_hp(),
                  all_combined = method_x$all_combined())

共有1个答案

郑星雨
2023-03-14

首先,我通常反对编写破坏功能可重复性的函数,因为我花了太多时间对基于未传递给它们的内容改变行为的函数进行故障排除。

但是,试试这个:

method_1 <- list(
  any_vs_four_gears = function(data = cur_data()) with(data, any(vs == 1 & gear == 4)),
  any_am_high_hp = function(data = cur_data()) with(data, any(am == 1 & hp > 170)),
  all_combined = function(data = cur_data()) with(data, all(any_vs_four_gears, any_am_high_hp))
)

mtcars %>%
  group_by(carb) %>%
  summarise(
    any_vs_four_gears = method_1$any_vs_four_gears()
    any_am_high_hp = method_1$any_am_high_hp(),
    all_combined = method_1$all_combined()
  )
# # A tibble: 6 x 4
#    carb any_vs_four_gears any_am_high_hp all_combined
#   <dbl> <lgl>             <lgl>          <lgl>       
# 1     1 TRUE              FALSE          FALSE       
# 2     2 TRUE              FALSE          FALSE       
# 3     3 FALSE             FALSE          FALSE       
# 4     4 TRUE              TRUE           TRUE        
# 5     6 FALSE             TRUE           FALSE       
# 6     8 FALSE             TRUE           FALSE       

这使用了< code>dplyr-pipe环境中的< code>cur_data()代词/函数,只添加了一点周围代码(< code>with(data,{...}),所以< code > { -表达式友好),并且“按原样”工作。

这些错误不难解释:

mtcars %>%
  select(-vs) %>%     # intentionally setting up an error
  group_by(carb) %>%
  summarise(
    any_vs_four_gears = method_1$any_vs_four_gears()
    any_am_high_hp = method_1$any_am_high_hp(),
    all_combined = method_1$all_combined()
  )
# Error: Problem with `summarise()` column `any_vs_four_gears`.
# i `any_vs_four_gears = method_1$any_vs_four_gears()`.
# x object 'vs' not found
# i The error occurred in group 1: carb = 1.
# Run `rlang::last_error()` to see where the error occurred.
 类似资料:
  • 问题内容: 你会怎么做? 或这个 : 最重要的是,我想知道何时在本地变量中存储值更有效,何时进行函数调用更好。 问题答案: 更具可读性更有效。临时表达式和局部变量需要相同的空间,从CPU / JVM的角度看,它们并没有太大区别。JVM将在优化/内嵌方面做得更好。 但是,如果方法调用很昂贵,则将其 缓存 在局部变量中。如果这只是一个简单的方法,无论如何都会内联。你的具体情况也恕我直言,局部变量 是

  • 问题内容: 如何在函数中创建或使用全局变量? 如果在一个函数中创建全局变量,如何在另一个函数中使用该全局变量?我是否需要将全局变量存储在需要对其进行访问的函数的局部变量中? 问题答案: 你可以在其他函数中使用全局变量,方法是像在分配给它的每个函数中一样声明它: 我想这是因为全局变量是如此危险,因此Python希望通过显式要求使用关键字来确保您真正知道这就是要使用的内容。

  • 问题内容: 我正在尝试在jquery的AJAX调用中使用变量,但是它不起作用。移动变量包含不同的值。请检查以下代码: 建议在数据中使用$ move变量的任何方法。 问题答案: 它应该是

  • 问题内容: 我从很多地方都听说过,全局变量本来就是讨厌和邪恶的,但是当使用一些非面向对象的Javascript时,我看不到如何避免它们。说我有一个函数,它使用复杂的算法使用随机数和填充物来生成数字,但是我需要在其他函数(回调或其他函数)中继续使用该特定数,因此不能成为同一函数的一部分。 如果最初生成的数字是局部变量,则无法从那里访问它。如果函数是对象方法,我可以将数字设为属性,但是它们不是属性,并

  • 本文向大家介绍Lua中的全局变量、非全局变量总结,包括了Lua中的全局变量、非全局变量总结的使用技巧和注意事项,需要的朋友参考一下 前言 Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”。这种组织结构的优点在于,其一,不需要再为全局变量创造一种新的数据结构,因此简化了Lua的内部实现;另一个优点是,可以像其他table一样操作这个table。为了便于实施这种操作,L

  • 我的代码检查用户是否可用。请参见下面的片段: 我唯一的问题是它包含对变量的不安全引用,因为我得到以下错误: 我四处搜索并摆弄了我的代码,但我无法摆脱这个错误。我不知道去哪里找了。