高效地找到最后一个连续的1序列中的第一个1。

huangapple go评论135阅读模式
英文:

Efficiently find the first of the last 1's sequence

问题

For test1 and test2, the expected output is 36 and 29, respectively.

Here is a sub-optimal solution:

  1. temp1 <- cumsum(test1)
  2. which(temp1==max(temp1[duplicated(temp1)&temp1!=max(temp1)]+1))[1]
  3. [1] 36
  4. temp2 <- cumsum(test2)
  5. which(temp2==max(temp2[duplicated(temp2)&temp2!=max(temp2)]+1))[1]
  6. [1] 29
英文:

I have the following vectors with 0s and 1s:

  1. test1 &lt;- c(rep(0,20),rep(1,5),rep(0,10),rep(1,15))
  2. test1
  3. [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  4. ^
  5. test2 &lt;- c(rep(0,8),rep(1,4),rep(0,5),rep(1,5),rep(0,6),rep(1,10),rep(0,2))
  6. test2
  7. [1] 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0
  8. ^

I need to find the index of first 1 in the last sequence of 1s (indicated by ^ in the above code). I have a solution (below) that doesn't perform well, how could I improve the performance?

For test1 and test2, the expected output is 36 and 29, respectively.

Here is a sub-optimal solution:

  1. temp1 &lt;- cumsum(test1)
  2. which(temp1==max(temp1[duplicated(temp1)&amp;temp1!=max(temp1)]+1))[1]
  3. [1] 36
  4. temp2 &lt;- cumsum(test2)
  5. which(temp2==max(temp2[duplicated(temp2)&amp;temp2!=max(temp2)]+1))[1]
  6. [1] 29

Note: The length of actual vectors is ~10k.

答案1

得分: 19

data.table库有一个未导出的函数叫做data.table:::uniqlist(list(x))。使用三个冒号:::来访问未导出的函数。该函数确定数据框的列何时更改值,并返回更改的索引。

  1. data.table:::uniqlist(list(test1))
  2. # [1] 1 21 26 36

关于uniqlist,可以参考@Arun在这里的讨论:https://stackoverflow.com/a/21267854/10276092

然后,我使用了y[length(y)]来找到向量中的最后一个项目,并使用基础的ifelse()来检查最后一个索引是否包含1,否则倒数第二个索引必须包含1。

  1. fx <- function(x) {
  2. y <- data.table:::uniqlist(list(x))
  3. ifelse(x[y[length(y)]] == 1, y[length(y)], y[length(y) - 1])
  4. }
英文:

The data.table library has a non-exported function called data.table:::uniqlist(list(x)). Use three colons ::: to access non-exported functions. This function determines when columns of a data.frame change value and return indices of the change.

  1. data.table:::uniqlist(list(test1))
  2. # [1] 1 21 26 36

@Arun talks about uniqlist here: https://stackoverflow.com/a/21267854/10276092

Then I use the y[length(y)] method of finding the last item in a vector, and base ifelse() to check if the last index contains a 1, else the second to last index must contain a 1.

  1. fx &lt;- function(x) {
  2. y &lt;- data.table:::uniqlist(list(x))
  3. ifelse(x[y[length(y)]] == 1, y[length(y)], y[length(y) - 1])
  4. }

答案2

得分: 18

使用 rle

  1. r <- rle(test1)
  2. ix <- max(which(r$values == 1))
  3. sum(r$lengths[1:(ix - 1)]) + 1
  4. # [1] 36
  5. r <- rle(test2)
  6. ix <- max(which(r$values == 1))
  7. sum(r$lengths[1:(ix - 1)]) + 1
  8. # [1] 29
英文:

Using rle:

  1. r &lt;- rle(test1)
  2. ix &lt;- max(which(r$values == 1))
  3. sum(r$lengths[ 1:(ix - 1) ]) + 1
  4. # [1] 36
  5. r &lt;- rle(test2)
  6. ix &lt;- max(which(r$values == 1))
  7. sum(r$lengths[ 1:(ix - 1) ]) + 1
  8. # [1] 29

答案3

得分: 18

另一种方法是使用 which + diff

  1. idx <- which(test1 == 1)
  2. idx[tail(which(c(0, diff(idx)) != 1), 1)]
  3. #[1] 36
英文:

Another way with which + diff.

  1. idx &lt;- which(test1 == 1)
  2. idx[tail(which(c(0, diff(idx)) != 1), 1)]
  3. #[1] 36

答案4

得分: 16

使用rle运行,然后使用cumsum计算每个运行的结束位置,减去长度并加1以获得起始位置,然后将其减少到仅包含1的运行,最后取最后一个元素。这给出了最后一组1的起始位置,但如果你想要:

  • 结束位置,只需省略-lengths+1
  • 最后一组0的运行,将==1替换为==0
  • 第一组1的运行,将tail替换为head

如果没有1,它将返回一个零长度的数字向量。

  1. with(rle(test1), tail((cumsum(lengths) - lengths + 1)[values == 1], 1))
英文:

Run rle and then use cumsum to calculate the end positions of each run and subtract the lengths and add 1 to get the start positions and then reduce that to the runs of 1's only and finally take the last element. This gives the start position of the last run of 1's but if you wanted:

  • the end position just omit the -lengths+1
  • the last run of 0's replace the ==1 with ==0
  • the first run of 1's replace tail with head

If there are no 1's it returns a zero length numeric vector.

  1. with(rle(test1), tail((cumsum(lengths) - lengths + 1)[values == 1], 1))

答案5

得分: 14

以下是您要翻译的内容:

For completeness, here is the benchmark with a vector of size 30001. Feel free to update this if needed.

  1. x &lt;- c(rep(0,14736),rep(1,413),rep(0,830),rep(1,961),rep(0,274),rep(1,12787))
  2. microbenchmark::microbenchmark(rle_zx8754(x),
  3. rle_Grothendieck(x),
  4. which_diff_Ma&#235;l(x),
  5. uniqlist_Viking(x),
  6. while_Ritchie(x),
  7. #Position_Ritchie(x),
  8. #detect_index_Ritchie(x),
  9. diff_Thomas(x),
  10. #regex_Thomas(x),
  11. #regexpr_Thomas(x),
  12. times = 1000, check=&#39;equal&#39;)
  13. Unit: microseconds
  14. expr min lq mean median uq
  15. rle_zx8754(x) 339.5 350.45 783.9827 357.45 375.15
  16. rle_Grothendieck(x) 352.7 364.75 616.2324 372.60 391.75
  17. which_diff_Ma&#235;l(x) 264.2 274.60 404.5521 279.50 292.00
  18. uniqlist_Viking(x) 16.7 22.30 32.1502 25.40 30.65
  19. while_Ritchie(x) 777.6 785.60 1021.0738 801.95 847.15
  20. diff_Thomas(x) 279.4 286.90 500.6373 291.20 306.35
  21. max neval cld
  22. 156630.3 1000 cd
  23. 11196.5 1000 bc
  24. 7263.2 1000 b
  25. 3524.9 1000 a
  26. 6739.7 1000 d
  27. 9435.5 1000 b

functions:

  1. x &lt;- c(rep(0,14736),rep(1,413),rep(0,830),rep(1,961),rep(0,274),rep(1,12787))
  2. rle_zx8754 &lt;- function(x){
  3. r &lt;- rle(x)
  4. ix &lt;- max(which(r$values == 1))
  5. sum(r$lengths[ 1:(ix - 1) ]) + 1
  6. }
  7. which_diff_Ma&#235;l &lt;- function(x){
  8. idx &lt;- which(x == 1)
  9. idx[tail(which(diff(idx) != 1), 1) + 1]
  10. }
  11. rle_Grothendieck &lt;- function(x){
  12. with(rle(x), tail((cumsum(lengths) - lengths + 1)[values == 1], 1))
  13. }
  14. uniqlist_Viking &lt;- function(x){
  15. y &lt;- data.table:::uniqlist(list(x))
  16. ifelse(x[y[length(y)]] == 1, y[length(y)], y[length(y) - 1])
  17. }
  18. while_Ritchie &lt;- function(x){
  19. l &lt;- length(x)
  20. while (x[l] - x[l - 1] != 1) {
  21. l &lt;- l - 1
  22. }
  23. l
  24. }
  25. Position_Ritchie &lt;- function(x){
  26. Position(isTRUE, diff(x) == 1, right = TRUE) + 1
  27. }
  28. detect_index_Ritchie &lt;- function(x){
  29. purrr::detect_index(diff(x) == 1, isTRUE, .dir = &quot;backward&quot;) + 1
  30. }
  31. diff_Thomas &lt;- function(x){
  32. max((2:length(x))[diff(x) == 1])
  33. }
  34. regex_Thomas &lt;- function(x){
  35. nchar(sub(&quot;(.*01).*&quot;, &quot;\\1&quot;, paste0(x, collapse = &quot;&quot;)))
  36. }
  37. regexpr_Thomas &lt;- function(x){
  38. attr(regexpr(&quot;.*(?&lt;=0)1&quot;, paste0(x,collapse = &quot;&quot;), perl = TRUE), &quot;match.length&quot;)
  39. }
英文:

For completeness, here is the benchmark with a vector of size 30001. Feel free to update this if needed.

  1. x &lt;- c(rep(0,14736),rep(1,413),rep(0,830),rep(1,961),rep(0,274),rep(1,12787))
  2. microbenchmark::microbenchmark(rle_zx8754(x),
  3. rle_Grothendieck(x),
  4. which_diff_Ma&#235;l(x),
  5. uniqlist_Viking(x),
  6. while_Ritchie(x),
  7. #Position_Ritchie(x),
  8. #detect_index_Ritchie(x),
  9. diff_Thomas(x),
  10. #regex_Thomas(x),
  11. #regexpr_Thomas(x),
  12. times = 1000, check=&#39;equal&#39;)
  13. Unit: microseconds
  14. expr min lq mean median uq
  15. rle_zx8754(x) 339.5 350.45 783.9827 357.45 375.15
  16. rle_Grothendieck(x) 352.7 364.75 616.2324 372.60 391.75
  17. which_diff_Ma&#235;l(x) 264.2 274.60 404.5521 279.50 292.00
  18. uniqlist_Viking(x) 16.7 22.30 32.1502 25.40 30.65
  19. while_Ritchie(x) 777.6 785.60 1021.0738 801.95 847.15
  20. diff_Thomas(x) 279.4 286.90 500.6373 291.20 306.35
  21. max neval cld
  22. 156630.3 1000 cd
  23. 11196.5 1000 bc
  24. 7263.2 1000 b
  25. 3524.9 1000 a
  26. 6739.7 1000 d
  27. 9435.5 1000 b

functions:

  1. x &lt;- c(rep(0,14736),rep(1,413),rep(0,830),rep(1,961),rep(0,274),rep(1,12787))
  2. rle_zx8754 &lt;- function(x){
  3. r &lt;- rle(x)
  4. ix &lt;- max(which(r$values == 1))
  5. sum(r$lengths[ 1:(ix - 1) ]) + 1
  6. }
  7. which_diff_Ma&#235;l &lt;- function(x){
  8. idx &lt;- which(x == 1)
  9. idx[tail(which(diff(idx) != 1), 1) + 1]
  10. }
  11. rle_Grothendieck &lt;- function(x){
  12. with(rle(x), tail((cumsum(lengths) - lengths + 1)[values == 1], 1))
  13. }
  14. uniqlist_Viking &lt;- function(x){
  15. y &lt;- data.table:::uniqlist(list(x))
  16. ifelse(x[y[length(y)]] == 1, y[length(y)], y[length(y) - 1])
  17. }
  18. while_Ritchie &lt;- function(x){
  19. l &lt;- length(x)
  20. while (x[l] - x[l - 1] != 1) {
  21. l &lt;- l - 1
  22. }
  23. l
  24. }
  25. Position_Ritchie &lt;- function(x){
  26. Position(isTRUE, diff(x) == 1, right = TRUE) + 1
  27. }
  28. detect_index_Ritchie &lt;- function(x){
  29. purrr::detect_index(diff(x) == 1, isTRUE, .dir = &quot;backward&quot;) + 1
  30. }
  31. diff_Thomas &lt;- function(x){
  32. max((2:length(x))[diff(x) == 1])
  33. }
  34. regex_Thomas &lt;- function(x){
  35. nchar(sub(&quot;(.*01).*&quot;, &quot;\\1&quot;, paste0(x, collapse = &quot;&quot;)))
  36. }
  37. regexpr_Thomas &lt;- function(x){
  38. attr(regexpr(&quot;.*(?&lt;=0)1&quot;, paste0(x,collapse = &quot;&quot;), perl = TRUE), &quot;match.length&quot;)
  39. }

答案6

得分: 12

一个简单的while循环将是一个(可能非常)快速的方法,其中所寻找的索引位于向量的末尾。

  1. f <- function(x) {
  2. l <- length(x)
  3. while (x[l] - x[l - 1] != 1) {
  4. l <- l - 1
  5. }
  6. l
  7. }

我们也可以使用Position()purrr的等效函数detect_index()

  1. Position(isTRUE, diff(test1) == 1, right = TRUE) + 1

或者

  1. purrr::detect_index(diff(test1) == 1, isTRUE, .dir = "backward") + 1
英文:

A simple while loop will be a (potentially very) fast approach where the sought index is towards the end of the vector.

  1. f &lt;- function(x) {
  2. l &lt;- length(x)
  3. while (x[l] - x[l - 1] != 1) {
  4. l &lt;- l - 1
  5. }
  6. l
  7. }
  8. f(test1)
  9. [1] 36
  10. f(test2)
  11. [1] 29

We could also use Position() or the purrr equivalent detect_index():

  1. Position(isTRUE, diff(test1) == 1, right = TRUE) + 1
  2. [1] 36
  3. purrr::detect_index(diff(test1) == 1, isTRUE, .dir = &quot;backward&quot;) + 1
  4. [1] 36

答案7

得分: 9

  • 'regex' approaches

您可以尝试使用正则表达式,像是sub + nchar:

  1. f1 <- function(v) nchar(sub("(.*01).*", "\\1", paste0(v, collapse = "")))

或者regexpr:

  1. f2 <- function(v) attr(regexpr(".*(?<=0)1", paste0(v, collapse = ""), perl = TRUE), "match.length")
  • 'diff' approaches

或者,您可以尝试其他的diff 方法,比如:

  1. f3 <- function(v) tail(which(diff(v) == 1) + 1, 1)

以及

  1. f4 <- function(v) max((2:length(v))[diff(v) == 1])
英文:

I believe you have many ways to do it, and below are some possible approaches:


  • regex approaches

You can try regex, like sub + nchar

  1. f1 &lt;- function(v) nchar(sub(&quot;(.*01).*&quot;, &quot;\\1&quot;, paste0(v, collapse = &quot;&quot;)))

or regexpr

  1. f2 &lt;- function(v) attr(regexpr(&quot;.*(?&lt;=0)1&quot;, paste0(v,collapse = &quot;&quot;), perl = TRUE), &quot;match.length&quot;)
  • diff approaches

Or, some other diff options, like

  1. f3 &lt;- function(v) tail(which(diff(v) == 1) + 1, 1)

and

  1. f4 &lt;- function(v) max((2:length(v))[diff(v) == 1])

答案8

得分: 9

另一种方法是使用 revmatchrev 反转向量,这样 match 就可以用于查找最后一个1序列。

或者使用 Rcpp 编写一个函数,实现相同的功能,但可以从末尾开始迭代。

或者使用 revdiffmatch

基准测试显示,Rcpp 函数是最快的,分配的内存最少。其性能取决于能够找到匹配的位置。

英文:

Another way using rev and match.
rev reverses the vector, so that match, which returns the first hit, can be used to find the last 1 sequence.

  1. f &lt;- \(x) {
  2. . &lt;- rev(x)
  3. i &lt;- match(1, .)
  4. if(is.na(i)) return(NA)
  5. j &lt;- match(0, tail(., -i))
  6. if(is.na(j)) 1
  7. else length(.) - i - j + 2 }
  8. f(test1)
  9. #[1] 36
  10. f(test2)
  11. #[1] 29
  12. f(c(1,1))
  13. #[1] 1
  14. f(c(0,1))
  15. #[1] 2
  16. f(c(1,0))
  17. #[1] 1
  18. f(c(0,0))
  19. #[1] NA

Or write a function using Rcpp doing the same but can iterate starting from the end.

  1. Rcpp::cppFunction(&quot;int f2(NumericVector x) {
  2. auto i = x.end();
  3. while(i != x.begin() &amp;&amp; *(--i) != 1.) ;
  4. while(i != x.begin() &amp;&amp; *(--i) == 1.) ;
  5. if(*i != 1.) ++i;
  6. return i == x.end() || *i != 1. ? 0 : i - x.begin() + 1;
  7. }&quot;)
  8. f2(test1)
  9. #[1] 36
  10. f2(test2)
  11. #[1] 29
  12. f2(c(1,1))
  13. #[1] 1
  14. f2(c(0,1))
  15. #[1] 2
  16. f2(c(1,0))
  17. #[1] 1
  18. f2(c(0,0))
  19. #[1] 0

Or using rev, diff and match.

  1. f3 &lt;- \(x) {
  2. i &lt;- match(-1, diff(rev(x)))
  3. if(is.finite(i)) length(x) - i + 1
  4. else if(x[1] == 1) 1
  5. else NA
  6. }
  7. f3(test1)
  8. #[1] 36
  9. f3(test2)
  10. #[1] 29
  11. f3(c(1,1))
  12. #[1] 1
  13. f3(c(0,1))
  14. #[1] 2
  15. f3(c(1,0))
  16. #[1] 1
  17. f3(c(0,0))
  18. #[1] NA

Benchmark

  1. uniqlist &lt;- function(x) { #M.Viking
  2. y &lt;- data.table:::uniqlist(list(x))
  3. ifelse(x[y[length(y)]] == 1, y[length(y)], y[length(y) - 1]) }
  4. which_diff &lt;- function(x) { #Ma&#235;l
  5. idx &lt;- which(x == 1)
  6. idx[tail(which(c(0, diff(idx)) != 1), 1)] }
  1. # Dataset from question
  2. x &lt;- rep(c(0,1,0,1,0,1), c(14736,413,830,961,274,12787))
  3. bench::mark(max_iterations = 1e5, f(x), f3(x), which_diff(x),
  4. uniqlist(x), f2(x) )
  5. # expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
  6. # &lt;bch:expr&gt; &lt;bch:tm&gt; &lt;bch:tm&gt; &lt;dbl&gt; &lt;bch:byt&gt; &lt;dbl&gt; &lt;int&gt; &lt;dbl&gt;
  7. #1 f(x) 199.07&#181;s 251.5&#181;s 3412. 1.21MB 76.3 1341 30
  8. #2 f3(x) 218.05&#181;s 319.61&#181;s 3144. 1.76MB 117. 1079 40
  9. #3 which_diff(x) 155.01&#181;s 177.53&#181;s 5518. 954.17KB 103. 2296 43
  10. #4 uniqlist(x) 17.04&#181;s 17.72&#181;s 55386. 1.36MB 4.04 27442 2
  11. #5 f2(x) 5.61&#181;s 6.13&#181;s 161213. 2.49KB 6.16 78462 3
  12. # Data with many changes between 0 and 1 and hit at end
  13. x &lt;- rep(c(0,1), 1e6)
  14. bench::mark(max_iterations = 1e5, f(x), f3(x), which_diff(x),
  15. uniqlist(x), f2(x) )
  16. # expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
  17. # &lt;bch:expr&gt; &lt;bch:tm&gt; &lt;bch:tm&gt; &lt;dbl&gt; &lt;bch:byt&gt; &lt;dbl&gt; &lt;int&gt; &lt;dbl&gt;
  18. #1 f(x) 17.97ms 19.86ms 44.6 76.29MB 50.5 23 26
  19. #2 f3(x) 28.77ms 32.78ms 25.6 114.44MB 52.9 14 29
  20. #3 which_diff(x) 14.47ms 16.91ms 52.3 68.67MB 67.8 27 35
  21. #4 uniqlist(x) 2.66ms 3ms 294. 7.63MB 27.8 148 14
  22. #5 f2(x) 1.08&#181;s 1.28&#181;s 701103. 2.49KB 21.0 100000 3
  23. # Data where hit is at beginning
  24. x &lt;- c(0,1,rep(0, 1e6))
  25. bench::mark(max_iterations = 1e5, f(x), f3(x), which_diff(x),
  26. uniqlist(x), f2(x) )
  27. # expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
  28. # &lt;bch:expr&gt; &lt;bch:tm&gt; &lt;bch:tm&gt; &lt;dbl&gt; &lt;bch:byt&gt; &lt;dbl&gt; &lt;int&gt; &lt;dbl&gt;
  29. #1 f(x) 4.34ms 6.6ms 131. 19.11MB 84.6 71 46
  30. #2 f3(x) 15.1ms 18.73ms 35.9 57.24MB 75.7 18 38
  31. #3 which_diff(x) 1.37ms 1.44ms 529. 7.63MB 93.9 265 47
  32. #4 uniqlist(x) 470.91&#181;s 491.54&#181;s 1994. 1.36MB 0 997 0
  33. #5 f2(x) 364.46&#181;s 375.08&#181;s 2649. 2.49KB 0 1325 0
  34. # Data where hit is at end
  35. x &lt;- c(rep(0, 1e6),1,0)
  36. bench::mark(max_iterations = 1e5, f(x), f3(x), which_diff(x),
  37. uniqlist(x), f2(x) )
  38. # expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
  39. # &lt;bch:expr&gt; &lt;bch:tm&gt; &lt;bch:tm&gt; &lt;dbl&gt; &lt;bch:byt&gt; &lt;dbl&gt; &lt;int&gt; &lt;dbl&gt;
  40. #1 f(x) 10.53ms 11.33ms 69.8 38.18MB 91.8 35 46
  41. #2 f3(x) 14.19ms 17.18ms 37.6 57.24MB 69.3 19 35
  42. #3 which_diff(x) 1.38ms 1.49ms 512. 7.63MB 77.9 256 39
  43. #4 uniqlist(x) 479.76&#181;s 491.61&#181;s 1997. 1.36MB 0 999 0
  44. #5 f2(x) 1.08&#181;s 1.28&#181;s 683440. 2.49KB 27.3 100000 4

The Rcpp function is the fastest and allocates the lowest amount of memory. Its performance depends where the match could be found.

答案9

得分: 4

  1. 也许不是最佳方法,但只是为了易于理解的替代方法
  2. ```r
  3. data.frame(var1=c(rep(0,20),rep(1,5),rep(0,10),rep(1,15))) %>%
  4. mutate(new=rleid(var1), row=row_number()) %>%
  5. filter(var1==1 & max(new)==new) %>%
  6. slice_head(n=1) %>%
  7. select(row)
  8. # 输出
  9. row
  10. 1 36
  1. <details>
  2. <summary>英文:</summary>
  3. May not be the best but just an alternate for easy understanding
  4. ```r
  5. data.frame(var1=c(rep(0,20),rep(1,5),rep(0,10),rep(1,15))) %&gt;%
  6. mutate(new=rleid(var1), row=row_number()) %&gt;%
  7. filter(var1==1 &amp; max(new)==new) %&gt;%
  8. slice_head(n=1) %&gt;%
  9. select(row)
  10. # output
  11. row
  12. 1 36

答案10

得分: 4

我们还可以使用data.table中的rleid函数:

  1. library(data.table)
  2. i1 <- rleid(test1)
  3. min(which(i1 == max(i1[test1 == 1])))
  4. # [1] 36
  5. i1 <- rleid(test2)
  6. min(which(i1 == max(i1[test2 == 1])))
  7. # [1] 29
英文:

We can also use rleid from data.table:

  1. library(data.table)
  2. i1 &lt;- rleid(test1)
  3. min(which(i1 == max(i1[test1 == 1])))
  4. # [1] 36
  5. i1 &lt;- rleid(test2)
  6. min(which(i1 == max(i1[test2 == 1])))
  7. # [1] 29

答案11

得分: 3

Using data.table::rleidv()

  1. rle_seq <- data.table::rleidv(test2)
  2. rle_ones <- rle_seq[test2 != 0]
  3. which_id_last <- rle_ones[length(rle_ones)]
  4. which(rle_seq == which_id_last)[1L]
  5. [1] 30001
英文:

Using data.table::rleidv()

  1. rle_seq &lt;- data.table::rleidv(test2)
  2. rle_ones &lt;- rle_seq[test2 != 0]
  3. which_id_last &lt;- rle_ones[length(rle_ones)]
  4. which(rle_seq == which_id_last)[1L]
  5. [1] 30001

huangapple
  • 本文由 发表于 2023年6月29日 22:46:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582182.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定