【问题标题】:Simplify horrible R code to adjust row means简化可怕的 R 代码以调整行均值
【发布时间】:2013-02-09 23:56:40
【问题描述】:

我知道使用 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 学习曲线上稍微上升了一点,这对我来说看起来很糟糕。也希望代码能够重新- 被其他人使用。真的很喜欢这门语言,如果我能找到更漂亮的方式,我会更喜欢它)

【问题讨论】:

  • apply(con1,1, sum) 和类似的行在您的代码中没有实际价值。您只需计算总和,不要将其存储在任何地方!
  • 感谢您的提示,但我已经知道了!它是为了在家用计算机上执行上述步骤的人的利益。它不包含在我正在使用的代码中,这会使它更加丑陋(如果可能的话:)

标签: r loops performance


【解决方案1】:

我认为这个单线应该可以完成这项工作:

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

【讨论】:

  • 也可以添加起始数据con1 &lt;- data.frame( array( round( rnorm( 15 , 10 , 3 ) ) , dim = c( 5 , 3 ) ) ) ; con2 &lt;- data.frame( array( c(8:13, 9:14, 10:15 ) , dim=c(5,3) ) )? :)
  • @AnthonyDamico 为什么?它是问题的前 7 行,因此无需在此重复。
  • EDi,这只是票:乘以脚本,您已经保存了大约 100 行代码,非常感谢。你已经证实了我对 R 的热爱! (诅咒自己自己没有弄清楚这一点。)将坚持通过犯错来学习最好的哲学。
【解决方案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) 将生成 rnormmean=5sd=2

【讨论】:

  • 非常感谢 iTech 这个有用的提示:刚刚意识到这是关于生成测试数据的评论,而不是尝试的答案。非常整洁。现在我需要零循环哇!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-09
  • 2023-01-22
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多