Cảm ơn ví dụ tái sản xuất. Đây là thứ R khá cơ bản. Bạn có thể gán cho thành phần được chọn của một vector (lưu ý một mảng có kích thước, và những gì bạn đã cho là một vector không phải là một mảng):
> pred_precipitation[pred_precipitation<0] <- 0
> pred_precipitation
[1] 1.2091281 0.0000000 7.7665555 0.0000000 0.0000000 0.0000000 0.5151504 0.0000000 1.8281251
[10] 0.5098688 2.8370263 0.4895606 1.5152191 4.1740177 7.1527742 2.8992215 4.5322934 6.7180530
[19] 0.0000000 1.1914052 3.6152333 0.0000000 0.3778717 0.0000000 1.4940469
cuộc chiến tranh Benchmark!
@James đã tìm thấy phương pháp thậm chí nhanh hơn và để lại trong nhận xét. Tôi tán thành anh ta, nếu chỉ vì tôi biết chiến thắng của anh ấy sẽ tồn tại trong thời gian ngắn.
Trước tiên, tôi cố gắng biên soạn, nhưng điều đó dường như không giúp bất cứ ai:
p <- rnorm(10000)
gsk3 <- function(x) { x[x<0] <- 0; x }
jmsigner <- function(x) ifelse(x<0, 0, x)
joshua <- function(x) pmin(x,0)
james <- function(x) (abs(x)+x)/2
library(compiler)
gsk3.c <- cmpfun(gsk3)
jmsigner.c <- cmpfun(jmsigner)
joshua.c <- cmpfun(joshua)
james.c <- cmpfun(james)
microbenchmark(joshua(p),joshua.c(p),gsk3(p),gsk3.c(p),jmsigner(p),james(p),jmsigner.c(p),james.c(p))
expr min lq median uq max
1 gsk3.c(p) 251.782 255.0515 266.8685 269.5205 457.998
2 gsk3(p) 256.262 261.6105 270.7340 281.3560 2940.486
3 james.c(p) 38.418 41.3770 43.3020 45.6160 132.342
4 james(p) 38.934 42.1965 43.5700 47.2085 4524.303
5 jmsigner.c(p) 2047.739 2145.9915 2198.6170 2291.8475 4879.418
6 jmsigner(p) 2047.502 2169.9555 2258.6225 2405.0730 5064.334
7 joshua.c(p) 237.008 244.3570 251.7375 265.2545 376.684
8 joshua(p) 237.545 244.8635 255.1690 271.9910 430.566
Nhưng chờ đợi! Dirk đã viết điều Rcpp này. Có thể một hoàn thành C++ không đủ năng lực đọc giấy JSS của mình, thích ứng với ví dụ của mình, và viết chức năng nhanh nhất của tất cả chúng? Hãy theo dõi, các thính giả thân yêu.
library(inline)
cpp_if_src <- '
Rcpp::NumericVector xa(a);
int n_xa = xa.size();
for(int i=0; i < n_xa; i++) {
if(xa[i]<0) xa[i] = 0;
}
return xa;
'
cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")
microbenchmark(joshua(p),joshua.c(p),gsk3(p),gsk3.c(p),jmsigner(p),james(p),jmsigner.c(p),james.c(p), cpp_if(p))
expr min lq median uq max
1 cpp_if(p) 8.233 10.4865 11.6000 12.4090 69.512
2 gsk3(p) 170.572 172.7975 175.0515 182.4035 2515.870
3 james(p) 37.074 39.6955 40.5720 42.1965 2396.758
4 jmsigner(p) 1110.313 1118.9445 1133.4725 1164.2305 65942.680
5 joshua(p) 237.135 240.1655 243.3990 250.3660 2597.429
Đó là khẳng định, đội trưởng.
Điều này sửa đổi đầu vào p
ngay cả khi bạn không gán cho nó. Nếu bạn muốn tránh hành vi đó, bạn phải sao chép:
cpp_ifclone_src <- '
Rcpp::NumericVector xa(Rcpp::clone(a));
int n_xa = xa.size();
for(int i=0; i < n_xa; i++) {
if(xa[i]<0) xa[i] = 0;
}
return xa;
'
cpp_ifclone <- cxxfunction(signature(a="numeric"), cpp_ifclone_src, plugin="Rcpp")
Thật không may giết được lợi thế về tốc độ.
Ari và @DirkEddelbuettel: Liệu nó thực sự thay đổi 'p' mà không gán? Dường như tôi không thử. – Aaron
@Aaron Xem giải thích của Dirk tại đây: http://stackoverflow.com/questions/11300048/rcpp-pass-by-reference-vs-by-value –