R中数组中变量的周期性

时间:2016-05-13 02:29:08

标签: r

假设我有alpha

alpha = c(a,a,a,b,c,c,c,a,c,c)

如何找到周期性,以便我可以构造另一个数组beta

beta = c(3,1,3,1,2)

没有在代码中使用alpha的内容?有没有办法使用线索或滞后来回答这个问题?

3 个答案:

答案 0 :(得分:1)

以下是使用tabulaterleid

的选项
library(data.table)
tabulate(rleid(alpha))
#[1] 3 1 3 1 2

答案 1 :(得分:1)

只是为了好玩,这是一个复杂的解决方案:

alpha <- c('a','a','a','b','c','c','c','a','c','c');
diff(c(0L,which(c(alpha[-1L]!=alpha[-length(alpha)],T))));
## [1] 3 1 3 1 2

解释

alpha[-1L]!=alpha[-length(alpha)];
## [1] FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE

首先计算一个逻辑向量,表示哪些相邻的输入元素对构成值相等的中断,哪些不相等。逻辑向量中每个元素的索引对应于输入向量中该对的第一个元素的索引。

c(alpha[-1L]!=alpha[-length(alpha)],T);
## [1] FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE

附加TRUE值以在向量的末尾创建伪中断。请参阅下一步以获得澄清。

which(c(alpha[-1L]!=alpha[-length(alpha)],T));
## [1]  3  4  7  8 10

将逻辑向量转换为表示输入向量中运行长度的端点的索引向量。现在应该清楚为什么我们必须在上一步中附加TRUE;否则将省略最终运行长度的终点。

c(0L,which(c(alpha[-1L]!=alpha[-length(alpha)],T)));
## [1]  0  3  4  7  8 10

前置零。这在概念上可以被认为是将索引向量变换为“边界向量”,其中每个元素表示输入向量运行长度的内部或外部边界。请参阅下一步以获得澄清。

diff(c(0L,which(c(alpha[-1L]!=alpha[-length(alpha)],T))));
## [1] 3 1 3 1 2

取连续边界之间的差异。这提供了所需的运行长度。

基准

library(data.table);
library(microbenchmark);

bgoldst <- function(alpha) diff(c(0L,which(c(alpha[-1L]!=alpha[-length(alpha)],T))));
akrun <- function(alpha) tabulate(rleid(alpha));
bethany <- function(alpha) { if (length(alpha)==0L) return(integer()); res <- integer(); last <- alpha[1L]; cnt <- 1L; i <- 2L; while (i<=length(alpha)) { if (alpha[i]==last) cnt <- cnt+1L else { res[length(res)+1L] <- cnt; last <- alpha[i]; cnt <- 1L; }; i <- i+1L; }; res[length(res)+1L] <- cnt; res; };
flick <- function(alpha) rle(alpha)$lengths;
alpha <- c('a','a','a','b','c','c','c','a','c','c');

expected <- c(3L,1L,3L,1L,2L);
identical(expected,bgoldst(alpha));
## [1] TRUE
identical(expected,akrun(alpha));
## [1] TRUE
identical(expected,bethany(alpha));
## [1] TRUE
identical(expected,flick(alpha));
## [1] TRUE

microbenchmark(bgoldst(alpha),akrun(alpha),bethany(alpha),flick(alpha));
## Unit: microseconds
##            expr     min       lq      mean   median       uq     max neval
##  bgoldst(alpha)   8.553  11.1200  14.85308  12.8300  15.3970  70.136   100
##    akrun(alpha) 129.151 144.9745 163.64182 156.7350 171.4895 313.898   100
##  bethany(alpha)  20.101  23.9500  30.43242  26.5155  37.8475  70.136   100
##    flick(alpha)  20.100  23.9495  30.44956  28.0120  32.2890  62.866   100
set.seed(1L); N <- 1e5L; alpha <- sample(letters[1:3],N,T);

expected <- bgoldst(alpha);
identical(expected,akrun(alpha));
## [1] TRUE
identical(expected,bethany(alpha));
## [1] TRUE
identical(expected,flick(alpha));
## [1] TRUE

microbenchmark(bgoldst(alpha),akrun(alpha),bethany(alpha),flick(alpha),times=10L);
## Unit: milliseconds
##            expr         min          lq        mean      median          uq         max neval
##  bgoldst(alpha)    5.497899    6.469098   11.007558    6.521699    7.297460   49.891634    10
##    akrun(alpha)    1.300492    1.370199    1.547461    1.401631    1.464282    2.816091    10
##  bethany(alpha) 2865.335271 2891.594408 2941.352229 2924.165053 2997.881411 3024.234204    10
##    flick(alpha)    8.060392    9.355323   13.646002   10.055176   10.841843   48.312741    10

答案 2 :(得分:0)

如果你想保持alpha盲区的值,你可以创建一个for循环并使用逻辑运行一个计数器,如果这个alpha迭代等于最后一个。您需要设置过去的alpha以接受当前值并将下一个值与之比较。

一旦两个值不一致,计数器编号就会连接到您在循环外创建的向量,计数器将返回到一个。

这很简单,你应该自己去做,以了解如何做。

您可以将文件读入变量,但不能手动输入数字或者需要使它们可见。如果数据受到保护&#39;在某种程度上...