【问题标题】:using apply to calculate across rows and columns使用 apply 跨行和列计算
【发布时间】:2012-01-31 17:35:35
【问题描述】:

我已经使用 apply 搜索了很长时间的解决方案,但我无法准确找到我需要的解决方案。我是从 Excel 过来的新 R 用户,需要计算与控件观察的百分比差异。一个真实的示例数据框如下所示:

site <- c(rep(1, 10), rep(2,10), rep(3,10))
element <-rep(c("ca", "Mg", "K"), 10)
control <- seq(from= 1,to=60, by=2)
BA01 <- seq(from= 31,to=90, by=2)
BA02 <- seq(from= 21,to=80, by=2)
BA03 <- seq(from= 101,to=160, by=2)
mydf <- data.frame(site, element, control, BA01, BA02,BA03)

其中 BA01 到 BA03 是不同的测试,将与对照进行比较。

我想做的就是制定一个这样的公式: ((BA01-control)/control)*100

并为每个测试列(BA01-BA03)和数据框中的每一行计算它。在 Excel 中,我可以复制并粘贴站点和元素列以及标题 BA01-BA03,在单元格 C2 中键入公式,然后根据需要将公式向右拖动,然后根据需要向下拖动并得到我的结果。在 R 中,我很难获得相同的结果。我已经尝试过申请,但无法使其正常工作。基本上,我希望将站点和元素作为第 1 列和第 2 列,然后是公式的结果,其中 BA01、BA02 和 BA03 作为列名。可能不会有什么不同,但我的真实数据框将有超过 130 列和数千行。

有人给我一些建议吗?
非常感谢您的帮助。

【问题讨论】:

    标签: r matrix dataframe apply


    【解决方案1】:

    如果我理解正确:

    cbind(mydf[1:2],sapply(mydf[-(1:3)],function(x) 100*(x-mydf[[3]])/mydf[[3]]))
       site element       BA01       BA02       BA03
    1     1      ca 3000.00000 2000.00000 10000.0000
    2     1      Mg 1000.00000  666.66667  3333.3333
    3     1       K  600.00000  400.00000  2000.0000
    4     1      ca  428.57143  285.71429  1428.5714
    5     1      Mg  333.33333  222.22222  1111.1111
    ...
    

    【讨论】:

      【解决方案2】:

      试试这个:

      cbind(mydf[1:2], 100 *  mydf[4:6] / mydf$control - 100)
      

      输出的前5行是:

         site element       BA01       BA02       BA03
      1     1      ca 3000.00000 2000.00000 10000.0000
      2     1      Mg 1000.00000  666.66667  3333.3333
      3     1       K  600.00000  400.00000  2000.0000
      4     1      ca  428.57143  285.71429  1428.5714
      5     1      Mg  333.33333  222.22222  1111.1111
      

      【讨论】:

        【解决方案3】:

        怎么样:

        pdiff <- function(x,y) (x-y)/y*100
        BAcols <- subset(mydf,select=c(BA01,BA02,BA03))  
        

        这个subset 对于一个小数据框是可读的,但是如果你真的有很多行想要规范化,你会想要通过使用数字范围来选择这些列,即mydf[,-(1:3)](删除前三列)或mydf[,4:ncol(mydf)](将第 4 列保留到最后)。

        cbind(mydf[,1:2],sweep(BAcols,1,mydf$control,pdiff))
        

         with(mydf,data.frame(site,element,sweep(BAcols,1,control,pdiff)))
        

        【讨论】:

        • 非常感谢两位的回复!两种解决方案都运行良好,并且完全满足了我的需求,现在我只需要做功课,这样我就可以更好地理解 R 中的功能,但至少现在我可以重新开始工作并成功跳过将结果导出到 excel 中并直接执行从数据库到 R。不过,我确实有一个问题要问詹姆斯。你为什么在 sapply 命令中使用两个 [] ?我尝试使用 [3] 并且成功了,但是我确信您推荐 [[3]] 是有原因的,这是为什么呢?
        猜你喜欢
        • 2019-07-22
        • 1970-01-01
        • 2011-05-27
        • 1970-01-01
        • 2019-09-29
        • 1970-01-01
        • 1970-01-01
        • 2020-10-31
        • 1970-01-01
        相关资源
        最近更新 更多