【问题标题】:Applying R function by row: data frame problems逐行应用 R 函数:数据框问题
【发布时间】:2018-07-10 08:14:14
【问题描述】:

我无法在 R 中创建一个函数,该函数允许我将一个单独的函数应用于数据帧的每一行,并将该函数的输出保存回数据帧。

一个简单的可重现示例(使用我想逐行应用的外部包/功能):

library(pwr)

n1 = c(22, 70)
n2 = c(25, 45)
df = data.frame(n1, n2)

我希望能够做到的是……:

df$pwr = pwr.t2n.test(n1= df$n1, n2 = df$n2, d = NULL, sig.level = .05, power = .80)[3]

我从数据框中为函数 n1 和 n2 参数输入 n1 和 n2 列。我收到了许多令人不快的错误/警告。

当我尝试使用 adply 逐行应用此函数时,会出现相同的错误/警告:

df= adply(df, 1, transform, pwr = pwr.t2n.test(n1= df$n1, n2 = df$n2, d = NULL, sig.level = .05, power = .80)[3])

但是,如果我一次将 pwr() 函数应用于一行,则为 n1 和 n2 参数指定数据框中的行和列位置,那么我就没有问题了:

pwr.t2n.test(n1= df[1,1], n2 = df[1,2], d = NULL, sig.level = .05, power = .80)[3] 
= [1] 0.836982

pwr.t2n.test(n1= df[2,1], n2 = df[2,2], d = NULL, sig.level = .05, power = .80)[3]
= [1] 0.5398989

我想知道是否有某种方法可以使用 pwr() 函数本身,或者搭载 adply 或类似的东西,以便在更大的数据框中应用此函数并保存结果对于每一行(给定它们的 n1 和 n2 参数)。

【问题讨论】:

    标签: r function


    【解决方案1】:

    @LAP 使用 base-R 所做的一个 tidyverse 版本:

    library(purrr)
    
    map_dfr(transpose(df), function(params){
      list(n1 = params$n1,
           n2 = params$n2,
           pw = pwr.t2n.test(n1 = params$n1, n2 = params$n2, d = NULL, sig.level = 0.05, power = 0.8)$d
      )
    })
    
    # A tibble: 2 x 3
         n1    n2    pw
      <dbl> <dbl> <dbl>
    1    22    25 0.837
    2    70    45 0.540
    

    提醒一下 - 在基准测试之后,@LAP 的解决方案看起来要快得多,所以如果您担心速度,请使用他们的解决方案。

    已编辑以解决后续问题:

    n1 = c(22, 70)
    n2 = c(25, 45)
    char_vec = c('h', 'i')
    df = data.frame(n1, n2, char_vec, stringsAsFactors = FALSE)
    
    map_dfr(transpose(df), function(params){
      # browser()
      list(n1 = params$n1,
           n2 = params$n2,
           pw = pwr.t2n.test(n1 = params$n1, n2 = params$n2, d = NULL, sig.level = 0.05, power = 0.8)$d,
           a_character_vec = params$char_vec
      )
    }) 
    
    # A tibble: 2 x 4
         n1    n2    pw a_character_vec
      <dbl> <dbl> <dbl> <chr>          
    1    22    25 0.837 h              
    2    70    45 0.540 i 
    

    【讨论】:

    • +1。太棒了,谢谢(以及为什么我需要学习 purrr 的一个很好的例子)。有没有一种简单的方法可以将原始数据帧中的几个字符向量转移到新的 tibble 中?看起来生成的新 tibble 的排列顺序不同,所以我不能简单地复制它。
    • 如果我理解正确,那应该不是问题 - 我已经更新了答案,在原始数据帧中包含一个额外的字符向量 char_vec,在结果数据帧中包含 a_character_vec
    • 正是我需要的!
    【解决方案2】:

    您可以使用索引使apply 工作:

    test <- apply(df, 1, function(x){
      pwr.t2n.test(n1 = x[1], n2 = x[2], d = NULL, sig.level = .05, power = .80)
    })
    
    [[1]]
    
         t test power calculation 
    
                 n1 = 22
                 n2 = 25
                  d = 0.836982
          sig.level = 0.05
              power = 0.8
        alternative = two.sided
    
    
    [[2]]
    
         t test power calculation 
    
                 n1 = 70
                 n2 = 45
                  d = 0.5398989
          sig.level = 0.05
              power = 0.8
        alternative = two.sided
    

    使用sapply从列表反馈它:

    df$new <- sapply(test, function(x){
      x$d
    })
    
      n1 n2       new
    1 22 25 0.8369820
    2 70 45 0.5398989
    

    【讨论】:

    • +1 感谢您展示如何使用 apply 完成此操作。当我将此解决方案与我感兴趣的(更大的)数据框一起使用时,它会引发一个奇怪的错误(抱怨 n1 和/或 n2 的某些行的观察值小于 2(我已经用 min() 进行了双重检查并且是不是这样)。有趣的是,我在下面@zack 的解决方案中没有遇到同样的错误。
    • 很奇怪。您的数据中有NA 吗?可能是 purrr 自动排除这些。无论如何,很高兴您为您的问题找到了可行的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2020-12-02
    • 2014-07-20
    • 2019-08-21
    • 1970-01-01
    相关资源
    最近更新 更多