使用适用于跨行和列计算

问题描述:

我已经搜索了很长时间,很难找到适用的解决方案,但我无法准确找到我需要的。我是一名来自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控制)/控制)* 100

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

有没有人对我有一些提示?
非常感谢您的帮助。

如果我理解正确:

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 
... 

如何:

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))) 
+0

谢谢都非常的答复!这两种解决方案都能很好地工作,并且准确地提供我需要的东西,现在我只需要做我的功课,这样我就可以更好地理解R中的函数,但至少现在我可以恢复工作并成功地跳过将结果导出到Excel并直接转到从数据库转变为R.但是我确实对詹姆斯有个疑问。你怎么在sapply命令中使用两个[]?我尝试过使用[3],但它确实有效,但我相信你有推荐[[3]]的原因,为什么? – 2012-02-01 09:11:53

试试这个:

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