简化可怕的R代码以调整行方式

时间:2013-02-24 21:23:52

标签: r loops performance

我知道使用R强大的矢量处理功能可以使代码更短,更高效。我现在还想不出来......

基本任务是调整每行中的单元格,以便强制行总数匹配由另一个数据帧确定的预定义数字。这样,每个区域的总人口被强制为一定值(每行代表一个区域),而从一列移动到下一列的单元格之间的比例保持不变。

这种丑陋的方式(第一个循环就是创建一个示例数据框;确保可以更好地完成所有;我只是不能停止使用循环!):

con1 <- array(dim=c(5,3))

set.seed(1066)
for(i in 1:ncol(con1)){
con1[,i] <- round(rnorm(n=5,mean=10,sd=3))}
con1 <- data.frame(con1)
con2 <- data.frame(array(c(8:13, 9:14, 10:15), dim=c(5,3)))

apply(con1,1, sum)
apply(con2,1, sum) # different row totals

con1.adj <- con1
for ( i in 1:nrow(con1)){
  con1.adj[i,1] <- con1[i,1] * ( sum(con2[i,]) / sum(con1[i,]) )
  con1.adj[i,2] <- con1[i,2] * ( sum(con2[i,]) / sum(con1[i,]) )
  con1.adj[i,3] <- con1[i,3] * ( sum(con2[i,]) / sum(con1[i,]) )
}
con1.adj <- data.frame(con1.adj)
apply(con1.adj,1, sum) # same row totals

(上下文:从其他人的工作中挖出这段代码并快乐地使用了一段时间。现在我看起来很糟糕,因为我已经在陡峭的R学习曲线上走了一小段路。也想要重新编写代码 - 被其他人使用。真正享受这种语言,如果我能找到一种更美妙的方式,我会更享受这种语言)

2 个答案:

答案 0 :(得分:15)

我认为这个单行应该做的工作:

con1.adj <- con1 * rowSums(con2) / rowSums(con1)

答案 1 :(得分:2)

以下是另一个以更好的方式生成con1的建议

rgen <- function(X,mean=10,sd=3){
  round(rnorm(n=length(X),mean=mean,sd=sd))
}

con1 <- data.frame(apply(con1,2,rgen))

请注意,随机向量的大小将与您的array维度相匹配,您可以动态地传递不同的meansd,例如apply(con1,2,rgen,5,2) rnorm将生成mean=5 sd=2和{{1}}