首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在一系列‘N’真中找到第一个真的位置

在一系列‘N’真中找到第一个真的位置
EN

Stack Overflow用户
提问于 2015-02-23 23:51:53
回答 3查看 124关注 0票数 3

从真[假]向量

代码语言:javascript
运行
复制
set.seed(1)
x = rnorm(1503501) > 0

我正在寻找一种执行(快速)方法,以获得第一组n TRUEs.的第一个真的位置。

我所处理的向量(x)完全包含1503501元素(除了一些短得多的元素)。下面是我目前的解决方案。它使用循环,但是循环在R中是非常慢的,有没有更好的,特别是更快的解决方案?

代码语言:javascript
运行
复制
n = 20

count = 0
solution = -1
for (i in 1:length(x)){
    if (x[i]){
        count = count + 1
        if (count == n){solution = i+1-n; break}
    } else {count = 0}
}
print(solution)
1182796

我正在考虑使用矢量化函数,做一些类似于y = which(x)或最终y = paste(which(x))的事情,并寻找特定的模式,但我不知道如何做到这一点。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-24 00:15:16

您可以使用Rcpp

代码语言:javascript
运行
复制
library(Rcpp)
cppFunction('int fC(LogicalVector x, int n) {
  int xs = x.size();
  int count = 0;
  int solution = -1;
  for (int i = 0; i < xs; ++i) {
    if (x[i]){
      if (++count == n){solution = i+2-n; break;}
    } else {
      count = 0;
    }
  }
  return solution;
}')

以下是一项小型基准研究:

代码语言:javascript
运行
复制
f1 <- function(x,n) {
  count = 0
  solution = -1
  for (i in 1:length(x)){
    if (x[i]){
      count = count + 1
      if (count == n){solution = i+1-n; break}
    } else {count = 0}
  }
  solution
}


set.seed(1)
x = rnorm(150350100) > 0
n = 20

print(f1(x,n)==fC(x,n))
# [1] TRUE


library(rbenchmark)
benchmark(f1(x,n),fC(x,n))
#       test replications elapsed relative user.self sys.self user.child sys.child
# 1 f1(x, n)          100  80.038  180.673    63.300   16.686          0         0
# 2 fC(x, n)          100   0.443    1.000     0.442    0.000          0         0

更新基准

代码语言:javascript
运行
复制
# Suggested by BondedDust
tpos <- function(x,pos) { rl <- rle(x); len <- rl$lengths; 
                          sum(len[ 1:(which( len == pos & rl$values==TRUE)[1]-1)],1)}

set.seed(1)
x = rnorm(1503501) > 0
n = 20

print(f1(x,n)==fC(x,n))
# [1] TRUE
print(f1(x,n)==tpos(x,n))
# [1] TRUE


benchmark(f1(x,n),fC(x,n),tpos(x,n),replications = 10)
#         test replications elapsed relative user.self sys.self user.child sys.child
# 1   f1(x, n)           10   4.756  110.605     4.735    0.020          0         0
# 2   fC(x, n)           10   0.043    1.000     0.043    0.000          0         0
# 3 tpos(x, n)           10   2.591   60.256     2.376    0.205          0         0
票数 4
EN

Stack Overflow用户

发布于 2015-02-24 00:03:48

看看这份成绩单(只使用一个小得多的随机样本)。我认为很清楚,编写一个函数可以很容易地选择满足联合条件的第一个位置,并在这一点之前的长度上使用累积和:

代码语言:javascript
运行
复制
> x = rnorm(1500) > 0

> rle(x)
Run Length Encoding
  lengths: int [1:751] 1 1 1 2 1 3 1 2 2 1 ...
  values : logi [1:751] FALSE TRUE FALSE TRUE FALSE TRUE ...
> table( rle(x)$lengths )

  1   2   3   4   5   6   7   8   9 
368 193  94  46  33  10   2   4   1 
> table( rle(x)$lengths , rle(x)$values)

    FALSE TRUE
  1   175  193
  2   100   93
  3    47   47
  4    23   23
  5    21   12
  6     5    5
  7     2    0
  8     3    1
  9     0    1
> which( rle(x)$lengths==8 & rle(x)$values==TRUE)
[1] 542
> which( rle(x)$lengths==7 & rle(x)$values==TRUE)
integer(0)
> which( rle(x)$lengths==6 & rle(x)$values==TRUE)
[1]  12 484 510 720 744

这是我的候选职能:

代码语言:javascript
运行
复制
 tpos <- function(x,pos) { rl <- rle(x); len <- rl$lengths; 
            sum(len[ 1:(which( len == pos & rl$values==TRUE)[1]-1)],1)}
 tpos(x,6)
#[1] 18

请注意,我从第一个索引中减去一个,这样就不会将TRUE的第一个限定运行的长度添加到该和中,从而计算出第一个这样的TRUE的位置。我猜第一轮n-真的位置将作为极值分布之一分布(尽管并不总是单调增长)。

代码语言:javascript
运行
复制
>  tpos(x,8)
[1] 1045
> tpos(x,8)
[1] 1045
> tpos(x,9)
[1] 1417
> tpos(x,10)
[1] 4806
> tpos(x,11)
[1] 2845
> tpos(x,12)
Error in 1:(which(len == pos & rl$values == TRUE)[1] - 1) : 
  NA/NaN argument
> set.seed(1)
> x = rnorm(30000) > 0
> tpos(x,12)
[1] 23509
票数 3
EN

Stack Overflow用户

发布于 2015-02-24 00:00:57

你可以拿出你的向量,在开头加一个假(零),删除结尾,然后把这个增广向量添加到原始向量中(作为整数的0/1向量),然后再做同样的事情,从先前增广的向量开始再添加一个假(零),然后删除结束,然后把它添加到当前滚动的和向量(再次,作为整数的向量),然后这样做,直到你把你的向量的n个总移位副本相加。然后您可以这样做( sum_x == n),其中sum_x是和向量,并取其中返回的最小值(),然后减去n-1,这将得到n真‘s连续出现的第一个开始。如果n比向量的长度稍小,这将工作得快得多。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28685834

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档