对data.table使用lapply(或任何替代方法)一次生成多个列

时间:2019-02-05 19:46:09

标签: r data.table

我有一个data.table,其中包含几个变量(列)及其标准错误。我想计算几件事,例如加权平均值,标准误差的平均值,p值...

玩具示例:

myDT <- data.table(ID=1:8, AA=21:28, BB=31:38, CC=41:48, stdAA=(11:18)/10, 
    stdBB=(11:18)/10, stdCC=(11:18)/10)
mycol <- c("AA", "BB", "CC")   # Select these ones.


   ID AA BB CC stdAA stdBB stdCC
1:  1 21 31 41   1.1   1.1   1.1
2:  2 22 32 42   1.2   1.2   1.2
3:  3 23 33 43   1.3   1.3   1.3
4:  4 24 34 44   1.4   1.4   1.4
5:  5 25 35 45   1.5   1.5   1.5
6:  6 26 36 46   1.6   1.6   1.6
7:  7 27 37 47   1.7   1.7   1.7
8:  8 28 38 48   1.8   1.8   1.8

OUTPUT1 <- myDT[,.(Variables=mycol,Estimate=lapply(mycol, 
   function (x) weighted.mean(get(x), 1/(get(paste0("std",x)))^2 ) ),
   Std.Error=lapply(mycol, function (x) mean(get(paste0("std",x)))))]  
OUTPUT1[,tvalue := as.numeric(Estimate)/as.numeric(Std.Error) ][,pvalue := 2*pt(-abs(tvalue),df=7)]


   Variables Estimate    Std.Error  tvalue       pvalue
        AA    23.76617      1.45   16.39046   7.671357e-07
        BB    33.76617      1.45   23.28702   6.833554e-08
        CC    43.76617      1.45   30.18357   1.129896e-08

我后来计算了最后两个列,因为它们需要一个先前计算的值,但是有一个问题,它会产生错误“二进制运算符的非数字参数”,正在使用“ as.numeric”。 我猜问题是生成的data.table包含列表而不是向量。 我想用一种更简单的语法来获取它,将所有内容都插入到同一个lapply中。

我该怎么办?

以下代码无法产生预期的输出,因为它在第二列的每个元素上插入了一个向量,因此我无法对其进行进一步的处理。

OUTPUT2 <- myDT[,.(mycol,lapply(mycol, function (x) 
  c(weighted.mean(get(x),1/(get(paste0("std",x)))^2 ),
   mean(get(paste0("std",x))) )))]

也许我需要添加某种类型的rbindlist,但是我无法正确执行。

尽管不短,但我的下一次尝试有效。 (而且我没有添加列名事件,因为它们已被删除,我需要稍后添加)

OUTPUT3 <- data.table(mycol,t(myDT[,c(lapply(mycol,
        function (x) .(weighted.mean(get(x),1/(get(paste0("std",x)))^2 ), 
           mean(get(paste0("std",x))))))]))
OUTPUT3[,tvalue := as.numeric(V1)/as.numeric(V2)][,pvalue := 2*pt(-abs(tvalue),df=7)]

将所有计算都放在一个lapply中会很棒。

2 个答案:

答案 0 :(得分:2)

如果先融化呢?它大大简化了问题:

melt(
  melt(myDT, 1:4, 5:7, 'Variable', 'StdError'), 
  c(1, 6),
  c('AA', 'BB', 'CC'),
  'Variable',
  'Estimate'
    )[, .(Variable, Estimate, StdError)
    ][
      , .(Estimate = weighted.mean(Estimate, 1 / StdError^2),
          StdError = mean(StdError)),
        .(Variable)
    ][
      , `:=`(tvalue    =  Estimate / StdError,
             pvalue    = 2 * pt(-abs(Estimate / StdError), df = 7)),
        .(Variable)
    ]

   Variable Estimate StdError   tvalue       pvalue
1:       AA 23.76617     1.45 16.39046 7.671357e-07
2:       BB 33.76617     1.45 23.28702 6.833554e-08
3:       CC 43.76617     1.45 30.18357 1.129896e-08

答案 1 :(得分:1)

有人可能会想出一些更优雅的东西。但是,如果目标是在单个lapply中计算所有内容:

library(data.table)
library(magrittr)

myDT <- data.table(ID=1:8, AA=21:28, BB=31:38, CC=41:48, stdAA=(11:18)/10, 
                   stdBB=(11:18)/10, stdCC=(11:18)/10)

mycol <- c("AA", "BB", "CC")   # Select these ones.

newCols <- c("Estimate", "Std.Error", "tvalue", "pvalue")

myDT[, .(lapply(mycol, function(x){
  estimate <- weighted.mean(get(x), 1/(get(paste0("std",x)))^2 )
  std.error <- mean(get(paste0("std",x)))
  tvalue <- estimate/std.error
  pvalue <- 2*pt(-abs(tvalue),df=7)
  out <- list(estimate, std.error, tvalue, pvalue)
  return(out)
}))] %>% rbindlist %>% 
  t(.) %>% 
  as.data.table(.) %>% 
  setnames(., names(.), newCols) %>% .[] # visualize table