逐行应用R函数:数据帧问题

时间:2018-07-09 21:39:15

标签: r function

我在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参数)。

2 个答案:

答案 0 :(得分: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 :(得分:2)

@LAP对base-R的简化版本:

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