首页 文章

R,有效方式,矩阵运算

提问于
浏览
1

我有一个大矩阵 . 目标是识别第1,2和3列中具有所有相等值的所有行,并计算每组行的第4列中的0的百分比 . 将所有这些百分比放在一个名为“data”的向量中 . 然后我需要三个向量(在每列上(最后一列除外)),它记录列的公共值 . 我们将这些向量称为:“factor1”,“factor2”和“factor3”,分别用于第1,2和3列 . 由于我的矩阵很大而且很多,我需要快速有效的计算 .

例如,我有这个矩阵:

[,1][,2][,3][,4]
[1,]  1    1   1   0
[2,]  1    2   1   0
[3,]  3    2   1   0.6
[4,]  1    1   1   0.2
[5,]  1    2   1   0
[6,]  1    1   2   0.1
[7,]  3    2   1   0.9

在这里,我们将第1行和第4行组合在一起(基于第1,2和3列中的相等值)并计算0的百分比(在第4列中)(%0等于0.5)

然后我们将行2和5分组并再次计算%0(等于1)

然后我们将行3和7分组并计算%0(等于0)

然后第6行是单独的,其%0(等于0)

这是我想要的矢量:

> data = c(0.5,1,0,0)

> factor1 = c(1,1,3,1)

> factor2 = c(1,2,2,1)

> factor3 = c(1,1,1,2)

这些值的顺序并不重要 . 如果向量“data”中的值0.5在位置2中,则所有因子的位置2应为1 .

然后目标是运行以下aov:

> aov(data ~ factor1 * factor2 * factor3)

非常感谢你的帮助

3 回答

  • 2

    重新创建矩阵:

    df <- read.table(text="[,1] [,2] [,3] [,4]
    [1,]  1    1   1   0
    [2,]  1    2   1   0
    [3,]  3    2   1   0.6
    [4,]  1    1   1   0.2
    [5,]  1    2   1   0
    [6,]  1    1   2   0.1
    [7,]  3    2   1   0.9",header=TRUE)
    m <- as.matrix(df)
    colnames(m) <- NULL
    

    使用package data.table进行split-apply-combine . 由于其效率,建议将data.table用于大型数据集 .

    library(data.table)
    DT <- as.data.table(m)
    
    DT.agg <- DT[,sum(V4==0)/length(V4),by=list(V1,V2,V3)]
    setnames(DT.agg,c("factor1","factor2","factor3","data"))
    print(DT.agg)
    #   factor1 factor2 factor3 data
    #1:       1       1       1  0.5
    #2:       1       2       1  1.0
    #3:       3       2       1  0.0
    #4:       1       1       2  0.0
    
    aov(data ~ factor1 * factor2 * factor3, data = DT.agg)
    
  • 0

    如果您的矩阵非常大,请不要忘记在尝试时包含转换为data.table的成本 . 以下应该非常快 .

    colnames(m) <- c(paste0('factor', 1:3), 'data')
    aggregate(data ~ ., data = m, function(x) mean(x!=0))
    

    然而我测试了它,结果发现plyr实际上与data.table相当具有竞争力,并且聚合相当远(3x) . 最近的版本plyr(1.8)已经比以前快得多 .

    在某些测试中,如果您首先转换为data.frame(即使包含data.frame转换时间),我发现聚合变得更快(2x) .

    发布的答案都没有真正缓慢 . 如果你在文件中,如果你的代码很慢,我猜你可能会遇到瓶颈 . 有一些方法可以优化文件的矩阵读取(使用 scan 而不是 read.table

    (顺便说一下,你可能不应该对这些数据进行ANOVA)

  • 2

    这是一个包含 plyr 包的解决方案 . 如果 m 是你的矩阵:

    m <- data.frame(m)
    colnames(m) <- c("V1","V2","V3","data")
    m2 <- ddply(m, .(V1,V2,V3), summarise, data=sum(data==0)/length(data))
    

    这使 :

    V1 V2 V3 data
    1  1  1  1  0.5
    2  1  1  2  0.0
    3  1  2  1  1.0
    4  3  2  1  0.0
    

    然后你可以这样做:

    aov(data=m2, data ~ V1 * V2 * V3)
    

    但是, plyr 并不总是最快的解决方案 .

相关问题