如果不使用for-loop,我怎样才能达到以下相同的效果?
df1 = data.frame( val = c("a", "c", "c", "b", "e") )
m1 = matrix(0, nrow=nrow(df1), ncol=length( c("a", "b", "c", "d", "e") ) )
colnames(m1) = c("a", "b", "c", "d", "e")
for(i in 1:nrow(df1)){
m1[i, df1[i, 1] ] = 1 #For each entry in dataframe, mark the respective column as 1
}
答案 0 :(得分:4)
此
f<-function(m1,df) {
for(i in 1:nrow(df1))
m1[i, df1[i, 1] ] = 1
return(m1)
}
相当于
g<-function(m1,df) {
m1[cbind(seq_len(nrow(df)),df1[,1])]<-1
return(m1)
}
对于这个特定的例子,后者更快
> microbenchmark(f(m1,df1),g(m1,df1))
Unit: microseconds
expr min lq mean median uq max neval cld
f(m1, df1) 167.085 174.885 194.58999 185.969 200.132 342.379 100 b
g(m1, df1) 20.116 22.990 27.12403 24.222 27.300 158.053 100 a
但请注意
答案 1 :(得分:0)
您的代码中有几个奇怪的东西。首先不需要df1,因为data.frame不应该存储一维向量。 val = c("a", "c", "c", "b", "e")
就够了。此外,正如其他人所说,有更紧凑(和一些更有效)的方法来实现同样的事情。但是,如果在实际问题中你使用了更多的数据并且发现它更容易用于循环,那么你应该考虑使用C ++代码(并且它的速度要快得多)。
这是我用来比较R和C ++ fors的基准测试,通过创建一个将添加前n个数字的函数(我做了n = 100K的测试)。
以下是代码:
library(Rcpp)
library(rbenchmark)
cppFunction(
'int cppSum(int n) {
int s = 0;
for(int i = 0; i <= n; i++) {
s += i;
}
return s;
}'
)
rSum <- function(n) {
s = 0
for (i in c(1:n)) {
s = s + i
}
return(s)
}
n = 100000
benchmark(rSum(n), cppSum(n))
结果如下:
test replications elapsed relative user.self sys.self user.child sys.child
2 cppSum(n) 100 0.008 1.00 0.00 0 0 0
1 rSum(n) 100 2.790 348.75 2.79 0 0 0
您可以在relative
列中注意到R函数比C ++函数慢348.75倍。在计算密集型过程中,使用C ++进行循环是一个很好的优化。有一次,我一直在运行一个for inside其他循环。这需要永远完成。当我用C ++更改了R for,它在几分钟内完成。
[编辑]
此示例无法解决您的实际问题。原始问题寻找替代缓慢的R for循环,所以我建议你选择更快的循环,即C++
for循环。工作示例不使用您的数据,因为它对于任何基准测试来说都太小了。相反,我使用100K
迭代循环,因此可以看到2个不同循环之间的差异。