将我的[r]答案扔到帽子里,针对速度进行了优化,并且可以在x的任何长度下工作(不像问号(Asker's)硬编码为长度20):
### data
set.seed(100)
x <- round(rnorm(20, sd = 0.02), 3)
### solution
summation <- c(x[1])
enn <- 1
n_of_seq <- c(enn)
for(i in 2:length(x)){
first <- x[i]
second <- summation[i - 1]
if(sign(first) == sign(second)){
summation <- c(summation, first + second)
enn <- enn + 1
}else{
summation <- c(summation, first)
enn <- 1
}
n_of_seq <- c(n_of_seq, enn)
}
并且,为了比较我当前(非常慢)的工作计算机上的运行时间,这是使用该线程中所有R解决方案的微基准测试的输出。毫不奇怪,进行最多复制和转换的解决方案往往会变慢。
Unit: microseconds
expr min lq mean median uq max neval
my_way() 13.301 19.200 23.38352 21.4010 23.401 20604.0 1e+05
author_way() 19.702 31.701 40.12371 36.0015 40.502 24393.9 1e+05
ronak() 856.401 1113.601 1305.36419 1236.8010 1377.501 453191.4 1e+05
ameer() 388.501 452.002 553.08263 491.3000 548.701 456156.6 1e+05
andrew() 2007.801 2336.801 2748.57713 2518.1510 2760.302 463175.8 1e+05
gonzo() 21.901 35.502 48.84946 43.9010 51.001 29519.5 1e+05
--------------编辑-------------- @nicola指出,对于更长的x,我的解决方案不是最快的-应该很明显,因为我通过使用x <-c(x,y)之类的调用不断制作矢量的副本。我只创建了长度= 20的最快解决方案,并且将其微基准化设置得尽可能低。
为了进行更公平的比较,我编辑了所有版本,以我认为最快的方式生成了原始代码,但是我对此表示欢迎。这是我非常慢的系统的完整基准测试代码和结果。我欢迎任何反馈。
# originally benchmarked a few different lengths
for(pie in c(100000)){
my_way<- function(){
set.seed(100)
x <- round(rnorm(pie, sd = 0.02), 3)
summation <- c(x[1])
enn <- 1
n_of_seq <- c(enn)
for(i in 2:length(x)){
first <- x[i]
second <- summation[i - 1]
if(sign(first) == sign(second)){
summation <- c(summation, first + second)
enn <- enn + 1
}else{
summation <- c(summation, first)
enn <- 1
}
n_of_seq <- c(n_of_seq, enn)
}
# print(summation)
}
author_way <- function(){
set.seed(100)
x <- round(rnorm(pie, sd = 0.02), 3)
sign_indicator <- ifelse(x > 0, 1,-1)
sky <- length(x)
number_of_sequence <- rep(NA, sky)
n <- 1
for (i in 2:sky) {
if (sign_indicator[i] == sign_indicator[i - 1]) {
n <- n + 1
} else{
n <- 1
}
number_of_sequence[i] <- n
}
number_of_sequence[1] <- 1
#############################
summation <- rep(NA, sky)
for (i in 1:sky) {
summation[i] <- sum(x[i:(i + 1 - number_of_sequence[i])])
}
}
# other ppls solutions:
ronak <- function(){
df <- data.table('x' = round(rnorm(pie, sd = 0.02), 3))
df[, c("n_of_sequence", "sum") := list(seq_len(.N), cumsum(x)),rleid(sign(x))]
}
ameer <- function(){
set.seed(100)
x <- round(rnorm(pie, sd = 0.02), 3)
run_lengths <- rle(sign(x))$lengths
n_of_sequence <- run_lengths %>% map(seq) %>% unlist
start <- cumsum(c(1,run_lengths))
start <- start[-length(start)] # start points of each series
map2(start,run_lengths,~cumsum(x[.x:(.x+.y-1)])) %>% unlist()
}
count_and_sum <- function(x){
set.seed(100)
x <- round(rnorm(pie, sd = 0.02), 3)
runs <- rle((x > 0) * 1)$lengths
groups <- split(x, rep(1:length(runs), runs))
output <- function(group) data.frame(x = group, n = seq_along(group), sum = cumsum(group))
result <- as.data.frame(do.call(rbind, lapply(groups, output)))
`rownames<-`(result, 1:nrow(result))
}
andrew <- function(){
set.seed(100)
df <- tibble(x = round(rnorm(pie, sd = 0.02), 3)) %>%
mutate(seqno = cumsum(c(1, diff(sign(x)) != 0))) %>% #identify sequence ids
group_by(seqno) %>% #group by sequences
mutate(n_of_sequence = row_number(), #count row numbers for each group
sum = cumsum(x)) %>% #cumulative sum for each group
ungroup() %>%
select(-seqno)
}
gonzo <- function(){
set.seed(100)
x <- round(rnorm(pie, sd = 0.02), 3)
n_of_sequence <- runner::streak_run(x > 0)
sum <- runner::sum_run(x, k = n_of_sequence)
}
mi1 <- microbenchmark(my_way(), author_way(), ronak(), ameer(), andrew(), gonzo(), times = 10)
print(mi1)
}
如这些结果所示,对于除我优化的长度以外的其他长度,我的版本很慢。x越长,在1000以上的所有东西上,它变得越慢的速度就会变得可笑。我最喜欢的版本是Ronak,它仅是系统上第二快的版本。到目前为止,GoGonzo在我的机器上是最快的。
Unit: milliseconds
expr min lq mean median uq max neval
my_way() 21276.9027 21428.2694 21604.30191 21581.97970 21806.9543 21896.7105 10
author_way() 82.2465 83.0873 89.42343 84.78315 85.3638 115.4550 10
ronak() 68.3922 69.3067 70.41924 69.84625 71.3509 74.7070 10
ameer() 481.4566 509.7552 521.19034 514.77000 530.1121 579.4707 10
andrew() 200.9654 202.1898 210.84914 206.20465 211.2006 233.7618 10
gonzo() 27.3317 28.2550 28.66679 28.50535 28.9104 29.9549 10
n_of_sequence
与所需的不相同