【问题标题】:Send "unclassed" variabel as function parameters?发送“未分类”变量作为函数参数?
【发布时间】:2020-02-07 13:30:22
【问题描述】:

或

如何创建自己的“...”变量?

函数通常返回一个特定的结构(或类)。有时函数的参数也是返回结构的一部分。操作结果后,如何将其作为参数发送给函数(或再次发送相同的函数)?

非常短的伪示例:

res1 <- power.t.test(alot of parameters)
res1b <- res1
res1b$some.parameter <- new-value
res2 <- power.t.test(parameters = unclass(res1b))

这是一个一般性问题,我在尝试解决特定问题时偶然发现了这个问题。我包含代码,希望能澄清我的问题:

set.seed(42); data <- rnorm(20) #to be able to reproduce

# Calculate how many pairs I need to find a difference of 1 ----
ptt1 <- power.t.test(delta = 1, sd = sd(data), sig.level = 0.05, power = 0.8, type = "paired", alternative = "two.sided")
# Paired t test power calculation
# 
# n = 15.55315
# delta = 1
# sd = 1.312628
# sig.level = 0.05
# power = 0.8
# alternative = two.sided
# 
# NOTE: n is number of *pairs*, sd is std.dev. of *differences* within pairs

# However, I wishing to know the exact power when changing n to next greater integer ----
ptt1$n <- ceiling(ptt1$n)
ptt1$power <- NULL
unclass(ptt1)
# $n
# [1] 16
# $delta
# [1] 1
# $sd
# [1] 1.312628
# $sig.level
# [1] 0.05
# $alternative
# [1] "two.sided"
# $note
# [1] "n is number of *pairs*, sd is std.dev. of *differences* within pairs"
# $method
# [1] "Paired t test power calculation"

# This is a solution ----
power.t.test.power <- function(ptt) {
  power.t.test(n = ceiling(ptt$n), delta = ptt$delta, sd = ptt$sd, sig.level = ptt$sig.level, type = ptt$type, alternative = ptt$alternative)
}

ptt1$type <- "paired" #power.t.test output (of class "power.htest") misses this named element
power.t.test.power(ptt1)
# Paired t test power calculation 
# 
# n = 16
# delta = 1
# sd = 1.312628
# sig.level = 0.05
# power = 0.8126338
# alternative = two.sided
# 
# NOTE: n is number of *pairs*, sd is std.dev. of *differences* within pairs

# BUT I WISHED that any of this would work, but all gives the same error ----
power.t.test(ptt1)
power.t.test(unclass(ptt1))
power.t.test(unlist(ptt1))
# Error in power.t.test(ptt1) : 
#   exactly one of 'n', 'delta', 'sd', 'power', and 'sig.level' must be NULL

【问题讨论】:

  • 我不确定,但我想你要找的是do.call(power.t.test,as.list(ptt1))
  • @iod - 成功了!但我不得不调整一些:ptt1$method
  • 有没有办法让函数调用忽略未使用的参数?因此我之前不需要清理变量。
  • @iod - 你能把你的评论写成答案吗(因为它主要回答了我的问题):D

标签: r ellipsis function-call function-parameter


【解决方案1】:

我看到你已经接受了另一个答案,但只是为了记录:

do.call 是调用函数并传递列表而不是单个参数的方式。在这种情况下,它将如下所示:

do.call(power.t.test,as.list(ptt1))

如果您只想传递一些参数,您可以使用出现在函数参数列表中的名称对向量进行子集化:

do.call(power.t.test,as.list(ptt1[names(ptt1) %in% formalArgs(power.t.test)]))

【讨论】:

    【解决方案2】:

    这是一种可能不是最优的解决方案,将结果指定为所有参数和结果的列表,并使用第一个参数的unlist 处理缺失的参数:

    af <- function(v1, v2 = NULL, v3 = NULL, v4 = NULL, res = NULL){
    
        if(is.null(v2)){
            cat("v2 null")
            v1 <- unlist(v1)
            v2 <- v1[2] ; v3 <- v1[3] ; res <- v1[5] ;
    
            v4 <- ifelse(is.null(res), v4, res)
            v1 <- v1[1]
        }
        return(list(v1 = v1, 
                v2 = v2, 
                v3 = v3, 
                v4 = v4, res = v1 + v2 + v3 + v4 ) )
    }
    
    r1 <- af(1, 1, 1, 1)
    r1
    af(r1)
    

    【讨论】:

    • 感谢您的回答!不过,我在理解它时遇到了一些麻烦。而且我认为@iod 的答案更接近我正在寻找的内容。
    【解决方案3】:

    您可以使用purrr::lift 将函数从接受参数... 更改为接受列表:

    ## power.t.test2 accepts arguments as a single list
    power.t.test2 <- purrr::lift( power.t.test )
    
    ## Modify outputs as needed
    ptt1$n <- ceiling(ptt1$n)
    ptt1$power <- NULL
    
    ## Reduce to a set of arguments that are accepted by the function
    a <- intersect(names(ptt1), formalArgs(power.t.test))
    
    ## Use the version that accepts the list
    power.t.test2( ptt1[a] )
    

    【讨论】:

      猜你喜欢
      • 2015-03-31
      • 1970-01-01
      • 2020-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 2014-12-28
      • 1970-01-01
      相关资源
      最近更新 更多