【问题标题】:which is the right apply for two numeric matrices?哪个是正确的适用于两个数字矩阵?
【发布时间】:2013-12-22 17:47:49
【问题描述】:

假设我有一个包含 1000 个x 观察值的向量和一个包含 1000 个 y 观察值的向量。 x的每一行和y的每一行分别对应100个样本。

x <- t(replicate(1000, rnorm(100,mean=6)))
y <- t(replicate(1000, rnorm(100,mean=5)))

我想进行 t.test 看看x 的每一行的平均值是否与y 的每一行的平均值有显着差异。

在这种情况下使用哪个apply 是正确的?理想情况下,应该是这样的:

Xapply(x,y, function(x,y) t.test(x,y)$conf.int)

这可能吗?

【问题讨论】:

    标签: r apply


    【解决方案1】:

    1) mapply 试试这个。 dt_xy 中的每一个转换为原始行的数据框,该数据框也是原始行的列表,允许直接使用mapply。您可能希望也可能不希望显示外部 t,具体取决于所需的输出方向:

    dt_ <- function(x) data.frame(t(x))
    conf.int.1 <- t(mapply(function(x, y) t.test(x, y)$conf.int, dt_(x), dt_(y)))
    

    1a) 使用公式符号的函数稍短变化。有关更多信息,请参阅 gsubfn home pagepackage documentation 上的 fn 信息

    library(gsubfn) # fn
    conf.int.1a <- t(fn$mapply(~ t.test(x, y)$conf.int, dt_(x), dt_(y)))
    

    2) 应用 另一种方法是从xy 创建一个3d 数组,然后在第一个维度上应用t 检验:

    z <- array(c(x, y), c(dim(x), 2))
    conf.int.2 <- t(apply(z, 1, function(x) t.test(x[, 1], x[, 2])$conf.int))
    

    2a) 使用abind 包中的abind 可以实现一种更好的创建3d 数组的方法:

    library(abind)
    a <- abind(x, y, along = 3)
    conf.int.2a <- t(apply(a, 1, function(x) t.test(x[, 1], x[, 2])$conf.int))
    

    更新:添加了解决方案 2。

    更新:添加了解决方案 2a。

    【讨论】:

    • 谢谢。对mapply 有任何性能问题吗?我问主要是因为我听说某些apply-s 实际上效率不高,这是一个玩具示例;在现实生活中,可能有超过 1000 个实验需要测试。
    • 您以前没有询问过性能...您给出的示例可能几乎可以立即使用此处建议的任何方法运行。如果您担心性能,您可以编辑您的问题以指定您真正的问题有多大……rbenchmarkmicrobenchmark 软件包很有用。
    • 不是一般意义上的。对于这个特殊问题,如果性能很重要,您将需要进行基准测试。
    【解决方案2】:

    一种方法是将它们 cbind 并在较大的对象上运行普通应用:

     apply( cbind(x,y), 1 , function(x) t.test(x[1:100], x[101:200] )$conf.int)
    

    【讨论】:

    • 我认为您可能必须将矩阵转换为数据框,或者使用x[1:100,]y[101:200,] ...?
    • 我不这么认为。当“cbound”对象命中匿名函数时,它是一个名为“x”的长度为 200 的向量。
    【解决方案3】:

    您可以组合这两个矩阵并为t.test 中使用的公式创建因子向量:

    fac <- gl(2, ncol(x)) # factor
    apply(cbind(x, y), 1, function(x) t.test(x ~ fac)$conf.int)
    

    【讨论】:

      【解决方案4】:
      set.seed(101)
      x <- t(replicate(1000, rnorm(100,mean=6)))
      y <- t(replicate(1000, rnorm(100,mean=5)))
      

      for 循环在这里实际上可以,但您可以在索引上使用 sapply

       result <- t(sapply(seq(nrow(x)),
                   function(i) t.test(x[i,],y[i,])$conf.int))
      

      或者(可能效率稍低)您可以将xy 转换为列表并使用mapply

       xList <- split(x,row(x))
       yList <- split(y,row(y))
       m1 <- mapply(t.test,xList,yList,SIMPLIFY=FALSE)
       result2 <- t(sapply(m1,"[[","conf.int"))
      

      【讨论】:

        【解决方案5】:

        我会使用mapply:

        t(mapply(function(i,j)t.test(x[i,],y[j,])$conf.int,
              seq(nrow(x)),seq(nrow(y))))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-27
          • 1970-01-01
          • 2016-05-18
          • 2011-08-28
          • 2015-01-29
          • 2020-07-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多