在R中,括号后面跟括号是什么意思

sf6xfgos  于 2023-01-06  发布在  其他
关注(0)|答案(3)|浏览(353)

在变异函数中使用scales::label_percent()的语法是不常见的,因为它使用了双括号:
label_percent()(an_equation_goes_here)
我想我以前没有在R中见过()()语法,我不知道如何查找它,因为我不知道它叫什么。我试过?()()和`??`()(),但都没有帮助。双括号语法叫什么?有人能推荐一个地方来阅读它吗?
下面是一个上下文示例:

library(tidyverse)
members <- 
  read_csv(
    paste0(
      "https://raw.githubusercontent.com/rfordatascience/tidytuesday/", 
      "master/data/2020/2020-09-22/members.csv"
    ), 
    show_col_types = FALSE)

members %>%
  count(success, died) %>%
  group_by(success) %>%
  # old syntax:
  # mutate(percent = scales::percent(n / sum(n))) 
  # new syntax:
  mutate(percent = scales::label_percent()(n / sum(n))) 
#> # A tibble: 4 × 4
#> # Groups:   success [2]
#>   success died      n percent
#>   <lgl>   <lgl> <int> <chr>  
#> 1 FALSE   FALSE 46452 98%    
#> 2 FALSE   TRUE    868 2%     
#> 3 TRUE    FALSE 28961 99%    
#> 4 TRUE    TRUE    238 1%

创建于2023年1月1日,使用reprex v2.0.2

ugmeyewa

ugmeyewa1#

大多数函数都返回一个值,无论是原子的(数字、整数、字符)、列表的(包括data.frame)还是更复杂的,对于这些函数来说,一组()(如您所知)只用于一次调用。
但是,偶尔函数调用会返回一个 function。例如,如果我们查看?scales::label_percent,我们可以向下滚动到

Value:

     All 'label_()' functions return a "labelling" function, i.e. a
     function that takes a vector 'x' and returns a character vector of
     'length(x)' giving a label for each input value.

让我们一步一步来看看:

fun <- scales::label_percent()
fun
# function (x) 
# {
#     number(x, accuracy = accuracy, scale = scale, prefix = prefix, 
#         suffix = suffix, big.mark = big.mark, decimal.mark = decimal.mark, 
#         style_positive = style_positive, style_negative = style_negative, 
#         scale_cut = scale_cut, trim = trim, ...)
# }
# <bytecode: 0x00000168ee5440e8>
# <environment: 0x00000168ee5501b8>
fun(0.35)
# [1] "35%"

scales::label_percent()的第一次调用返回了一个函数,然后我们可以使用该函数,并使用任意多的参数。
如果不想将返回的函数存储在fun这样的变量中,可以在第一组()后面加上另一组括号,立即使用它。

scales::label_percent()(0.35)
# [1] "35%"

一个相关的问题是 “为什么你想让一个函数返回另一个函数?" 风格上的原因有很多,但在scales::label_*的情况下,它们被设计用于需要将选项表示为函数而不是静态值的地方,例如,它可以用在ggplot代码中:通常使用简单的试探法来方便地放置轴刻度,以确定刻度标记的计数、位置和呈现。虽然可以使用ggplot2::scale_*_manual(values = ...)来手动控制刻度的数量、位置和外观,但通常更方便的是不预先关心刻度的数量或位置,并且在使用刻面的情况下,它可以根据刻面变量而变化(s),所以不是一个可以轻易赋值给静态变量的函数,在这种情况下,最好是赋值给一个给定了一些简单参数的函数(如轴的最小值/最大值),并且该函数返回一些有意义的值。
为什么我们不能直接传递scales::label_percent呢?(问得好)即使您在这里的调用中使用默认值,您也可能希望更改任何或所有可控制的内容,例如:

  • suffix=默认为"%",但也许您需要一个如" %"中的空格?
  • decimal.mark=默认为".",但也许您的区域设置更喜欢逗号?

虽然对于这些选项的所有组合具有多个函数是可行的,但是从长远来看,提供用于创建函数的“模板函数”通常更容易,例如

fun <- scales::label_percent(accuracy = 0.01, suffix = " %", decimal.mark = ",")
fun(0.353)
# [1] "35,30 %"
scales::label_percent(accuracy = 0.01, suffix = " %", decimal.mark = ",")(0.353)
# [1] "35,30 %"
dced5bon

dced5bon2#

在R中,一个 * 表达式 * 后跟圆括号中的参数列表((/))称为 * 函数调用 *。
没有必要为一行中的两个函数调用指定一个特殊的名称,它们仍然只是函数调用。

kmbjn2e3

kmbjn2e33#

如果我们运行一个函数,而这个函数返回的值本身也是一个函数,那么我们也可以调用一个函数。
例如,我们首先运行f,用f()赋值返回值给g,但是返回值本身是一个函数,所以g是一个函数-,是函数function() 3-,我们也可以运行它。

# f is a function which returns a function
f <- function() function() 3  

g <- f()  # this runs f which returns `function() 3`
g()  # thus g is a function so we can call it
## [1] 3

现在把所有这些放在一起,我们可以把它写在一行中

f()()
## [1] 3

如图所示,()只有一个含义,而两个含义在一起的事实仅仅是因为我们调用了一个调用的结果。

相关问题