首页 文章

如何用R中的向量元素划分矩阵的每一行

提问于
浏览
51

我想用固定向量划分矩阵的每个 row . 例如

mat<-matrix(1,ncol=2,nrow=2,TRUE)
dev<-c(5,10)

mat/dev 将每个 column 除以 dev .

[,1] [,2]
[1,]  0.2  0.2
[2,]  0.1  0.1

但是,我希望得到这个结果,即执行操作 row-wise

rbind(mat[1,]/dev, mat[2,]/dev)

     [,1] [,2]
[1,]  0.2  0.1
[2,]  0.2  0.1

到那儿有明确的命令吗?

2 回答

  • 4

    以下是增加代码长度的几种方法:

    t(t(mat) / dev)
    
    mat / dev[col(mat)] #  @DavidArenburg & @akrun
    
    mat %*% diag(1 / dev)
    
    sweep(mat, 2, dev, "/")
    
    t(apply(mat, 1, "/", dev))
    
    plyr::aaply(mat, 1, "/", dev)
    
    mat / rep(dev, each = nrow(mat))
    
    mat / t(replace(t(mat), TRUE, dev))
    
    mapply("/", as.data.frame(mat), dev)  # added later
    
    mat / matrix(dev, nrow(mat), ncol(mat), byrow = TRUE)  # added later
    
    do.call(rbind, lapply(as.data.frame(t(mat)), "/", dev))
    
    mat2 <- mat; for(i in seq_len(nrow(mat2))) mat2[i, ] <- mat2[i, ] / dev
    

    数据框

    如果 mat 是数据帧并且产生数据帧结果,则以 mat / 开头的所有解决方案也可以工作 . sweep 解决方案和最后一个解决方案(即 mat2 )的情况也是如此 . mapply 解决方案适用于data.frames但生成矩阵 .

    矢量

    如果 mat 是普通矢量而不是矩阵,则其中任何一个都返回一个列矩阵

    t(t(mat) / dev)
    mat / t(replace(t(mat), TRUE, dev))
    

    这一个返回一个向量:

    plyr::aaply(mat, 1, "/", dev)
    

    其他人给出错误,警告或不是所需的答案 .

    基准

    代码的简洁和清晰可能比速度更重要,但为了完整性,这里有一些使用10次重复然后100次重复的基准 .

    library(microbenchmark)
    library(plyr)
    
    set.seed(84789)
    
    mat<-matrix(runif(1e6),nrow=1e5)
    dev<-runif(10)
    
    microbenchmark(times=10L,
      "1" = t(t(mat) / dev),
      "2" = mat %*% diag(1/dev),
      "3" = sweep(mat, 2, dev, "/"),
      "4" = t(apply(mat, 1, "/", dev)),
      "5" = mat / rep(dev, each = nrow(mat)),
      "6" = mat / t(replace(t(mat), TRUE, dev)),
      "7" = aaply(mat, 1, "/", dev),
      "8" = do.call(rbind, lapply(as.data.frame(t(mat)), "/", dev)),
      "9" = {mat2 <- mat; for(i in seq_len(nrow(mat2))) mat2[i, ] <- mat2[i, ] / dev},
     "10" = mat/dev[col(mat)])
    

    赠送:

    Unit: milliseconds
     expr         min          lq       mean      median          uq        max neval
        1    7.957253    8.136799   44.13317    8.370418    8.597972  366.24246    10
        2    4.678240    4.693771   10.11320    4.708153    4.720309   58.79537    10
        3   15.594488   15.691104   16.38740   15.843637   16.559956   19.98246    10
        4   96.616547  104.743737  124.94650  117.272493  134.852009  177.96882    10
        5   17.631848   17.654821   18.98646   18.295586   20.120382   21.30338    10
        6   19.097557   19.365944   27.78814   20.126037   43.322090   48.76881    10
        7 8279.428898 8496.131747 8631.02530 8644.798642 8741.748155 9194.66980    10
        8  509.528218  524.251103  570.81573  545.627522  568.929481  821.17562    10
        9  161.240680  177.282664  188.30452  186.235811  193.250346  242.45495    10
       10    7.713448    7.815545   11.86550    7.965811    8.807754   45.87518    10
    

    重新运行所有那些花费<20毫秒,重复100次的测试:

    microbenchmark(times=100L,
      "1" = t(t(mat) / dev),
      "2" = mat %*% diag(1/dev),
      "3" = sweep(mat, 2, dev, "/"),
      "5" = mat / rep(dev, each = nrow(mat)),
      "6" = mat / t(replace(t(mat), TRUE, dev)),
     "10" = mat/dev[col(mat)])
    

    赠送:

    Unit: milliseconds
     expr       min        lq      mean    median        uq       max neval
        1  8.010749  8.188459 13.972445  8.560578 10.197650 299.80328   100
        2  4.672902  4.734321  5.802965  4.769501  4.985402  20.89999   100
        3 15.224121 15.428518 18.707554 15.836116 17.064866  42.54882   100
        5 17.625347 17.678850 21.464804 17.847698 18.209404 303.27342   100
        6 19.158946 19.361413 22.907115 19.772479 21.142961  38.77585   100
       10  7.754911  7.939305  9.971388  8.010871  8.324860  25.65829   100
    

    所以在这两个测试中#2(使用 diag )是最快的 . 原因可能在于它几乎直接诉诸于BLAS,而#1依赖于成本较高的 t .

  • 100

    您正在寻找应用于行的 apply 函数:

    t(apply(mat, 1, function(x) x/dev))
    

相关问题