我在R中有一个数据框,它包含两个(数字)列,比如A和B.我想构造一个由元素组成的列
A1+B1
(A1+B1)*A2+B2
((A1+B1)*A2+B2)*A3+B3
...
这可能是一个简单的单行,但我没有看到它。
编辑:从标题中删除了矢量化的单词,因为我基本上只对任何优雅的解决方案感兴趣(我自己可以做的愚蠢的解决方案)。在F#中 - 我更熟悉 - 这就像是(假设元素在列表中作为元组,这将更加惯用):
ABlist |> List.fold (fun acc (a,b) -> acc*a+b) 1
这仍然是非常简短明了的事情。我拖了它,因为我是一个R菜鸟并且不熟悉它,但是我已经在某个地方读到它是一种功能语言,所以我猜一个解决方案就折叠而言数据框架会存在吗?
答案 0 :(得分:3)
这是由于Bram使用Reduce失败而导致的不同答案。它构建一个具有A; B对的列表,然后将累加器的初始值设置为1,这样第一次乘法就不会被清零:
abList <- mapply(c, A,B, SIMPLIFY=FALSE) # keeps as a list
Reduce( function(acc,x) {acc*x[1]+x[2]},
abList,init=c(1,0),
accumulate=TRUE)[-1] # removes the initialization value
#--------
[[1]]
[1] 4 3
[[2]]
[1] 10 8
[[3]]
[1] 31 25
[[4]]
[1] 128 104
[[5]]
[1] 645 525
可能需要进一步使用s/lapply( ..., "[", 1)
来拉出累加器
> sapply( Reduce( function(acc,x) {acc*x[1]+x[2]},
+ abList,init=c(1,0),
+ accumulate=TRUE)[-1], "[", 1)
[1] 4 10 31 128 645
答案 1 :(得分:2)
好吧,事实证明我太懒了,我自己弄清楚了(注意:在此之前已经有一个很好的答案使用Rcpp,但我不能在工作中使用它)。基本上只是我在编辑中写的关于如何在F#中执行此操作的R的翻译:
a <- c(1,2,3)
b <- c(4,5,6)
abList <- list(a,b)
Reduce( function(acc,x) {acc*x[[1]]+x[[2]]},
abList,
accumulate=TRUE)
诀窍。编辑:根据下面的评论,它实际上没有做到这一点。如果构建abList by
abList <- apply(rbind(a,b),2,as.pairlist)
然后折叠:
Reduce(function(acc,x) {(acc*x[[1]])+x[[2]]},abList,1,accumulate=TRUE)
一个人得到了正确的答案(前面有一个1,因为这是累加器的初始值)
答案 2 :(得分:1)
这在Rcpp中相对简单,如果您尝试使用R中的循环实现此功能,则不会出现性能问题。
library(Rcpp)
sum.prod <- cppFunction(
"NumericVector sum_prod(NumericVector x, NumericVector y) {
NumericVector result(x.size());
result[0] = x[0] + y[0];
for (int i=1; i < x.size(); ++i) result[i] = result[i-1]*x[i] + y[i];
return result;
}")
sum.prod(c(1, 2, 3, 4, 5), c(3, 2, 1, 4, 5))
# [1] 4 10 31 128 645
我发现Rcpp是加速难以矢量化计算的最简单方法。
答案 3 :(得分:1)
X = 1; for ( i in seq(length(A) ) ) { X= B[i]+A[i]*X; print(X) }
[1] 4
[1] 10
[1] 31
[1] 128
[1] 645
如果你想积累而不是重复:
X = 1; for ( i in seq(length(A) ) ) { X[1+i]= B[i]+A[i]*X[i] }; X[-1]
#[1] 4 10 31 128 645
与Rcpp解决方案相比,速度会慢得多,但是如果您需要动态进行编译步骤,那么只有当长度超过1000时,您才会注意到差异:
> A <- sample(1:10000, 1000); B <- sample(1:10000, 1000)
> system.time( {X = 1; for ( i in seq(length(A) ) ) { X[1+i]= B[i]+A[i]*X[i] }; X[-1]})
user system elapsed
0.014 0.002 0.017
> library(Rcpp)
> system.time( {sum.prod <- cppFunction(
+ "NumericVector sum_prod(NumericVector x, NumericVector y) {
+ NumericVector result(x.size());
+ result[0] = x[0] + y[0];
+ for (int i=1; i < x.size(); ++i) result[i] = result[i-1]*x[i] + y[i];
+ return result;
+ }")
+ sum.prod(A,B) } )
user system elapsed
0.012 0.002 0.014