使用R编码序列长度

时间:2011-08-16 11:45:53

标签: r encoding

有没有办法在R中编码增加的整数序列,类似于使用游程长度编码(rle)编码游程长度?

我将举例说明:

类比:游程编码

r <- c(rep(1, 4), 2, 3, 4, rep(5, 5))
rle(r)
Run Length Encoding
  lengths: int [1:5] 4 1 1 1 5
  values : num [1:5] 1 2 3 4 5

所需:序列长度编码

s <- c(1:4, rep(5, 4), 6:9)
s
[1] 1 2 3 4 5 5 5 5 6 7 8 9

somefunction(s)
Sequence lengths
  lengths: int [1:4] 5 1 1 5
  value1 : num [1:4] 1 5 5 5

修改1

因此,somefunction(1:10)将给出结果:

Sequence lengths
  lengths: int [1:1] 10
  value1 : num [1:1] 1 

这个结果意味着有一个长度为10的整数序列,起始值为1,即seq(1, 10)

请注意,我的示例结果中没有错误。实际上,载体以序列5:9结束,而不是6:9,用于构建它。

我的用例是我正在使用SPSS导出文件中的调查数据。问题网格中的每个子问题都将具有模式paste("q", 1:5)的名称,但有时会有一个“其他”类别,该类别将标记为q_99q_other或其他内容。我希望找到一种识别序列的方法。

修改2

在某种程度上,我所需的函数是基函数sequence的反函数,在我的示例中添加了起始值value1

lengths <- c(5, 1, 1, 5)
value1 <- c(1, 5, 5, 5)

s
[1] 1 2 3 4 5 5 5 5 6 7 8 9
sequence(lengths) + rep(value1-1, lengths) 
[1] 1 2 3 4 5 5 5 5 6 7 8 9

编辑3

我应该说,为了我的目的,序列被定义为增加整数序列,而不是单调递增序列,例如c(4,5,6,7)但不是c(2,4,6,8)也不是c(5,4,3,2,1)。但是,序列之间可能出现任何其他整数。

这意味着解决方案应该能够应对这个测试用例:

somefunction(c(2, 4, 1:4, 5, 5))
    Sequence lengths
      lengths: int [1:4] 1 1 5 1
      value1 : num [1:4] 2 4 1 5 

在理想情况下,解决方案还可以处理最初建议的用例,其中包括向量中的字符,例如

somefunction(c(2, 4, 1:4, 5, "other"))
    Sequence lengths
      lengths: int [1:5] 1 1 5 1 1
      value1 : num [1:5] 2 4 1 5 "other"

6 个答案:

答案 0 :(得分:8)

编辑:添加控件以执行角色向量。

基于rle,我来看下面的解决方案:

somefunction <- function(x){

    if(!is.numeric(x)) x <- as.numeric(x)
    n <- length(x)
    y <- x[-1L] != x[-n] + 1L
    i <- c(which(y|is.na(y)),n)

    list(
      lengths = diff(c(0L,i)),
      values = x[head(c(0L,i)+1L,-1L)]
    )

}

> s <- c(2,4,1:4, rep(5, 4), 6:9,4,4,4)

    > somefunction(s)
    $lengths
    [1] 1 1 5 1 1 5 1 1 1

    $values
    [1] 2 4 1 5 5 5 4 4 4

这个适用于我尝试的每个测试用例,并使用没有ifelse子句的矢量化值。应该跑得更快。它将字符串转换为NA,因此您保持数字输出。

> S <- c(4,2,1:5,5, "other" , "other",4:6,2)

> somefunction(S)
$lengths
[1] 1 1 5 1 1 1 3 1

$values
[1]  4  2  1  5 NA NA  4  2

Warning message:
In somefunction(S) : NAs introduced by coercion

答案 1 :(得分:5)

这是我的解决方案

diff_s = which(diff(s) != 1)
lengths = diff(c(0, diff_s, length(s)))
values  = s[c(1, diff_s + 1)]

编辑:处理字符串的功能

sle2 = function(s){
  s2 = as.numeric(s)
  s2[is.na(s2)] = 100 + as.numeric(factor(s[is.na(s2)]))
  diff_s2 = which(diff(s2) != 1)
  lengths = diff(c(0, diff_s2, length(s)))
  values  = s[c(1, diff_s2 + 1)]
  return(list(lengths = lengths, values = values))
}

sle2(c(4,2,1:5,5, "other" , "other",4:6,2, "someother", "someother"))

lengths
 [1] 1 1 5 1 1 1 3 1 1 1

$values
 [1] "4"   "2"  "1"   "5"  "other" "other"  "4"   "2"  "someother" "someother"

Warning message:
In sle2(c(4, 2, 1:5, 5, "other", "other", 4:6, 2, "someother", "someother")) :
  NAs introduced by coercion

答案 2 :(得分:4)

您可以使用此功能开始(上面给出s):

s2<-c(0, diff(s))
s3<-ifelse((c(s2[-1], 0)==1) & (s2!=1), 1, s2)
rle(ifelse(s3==1, -1, seq_along(s3)))

它还没有返回值,可能有足够的方法来adpat代码。至少你有序列长度,因此你可以很容易地检索序列的起始值。

答案 3 :(得分:3)

怎么样:

sle <- function(s)
{
    diffs <- which(diff(s)!=1)
    lengths <- c(diffs[1],diff(diffs),length(s)-diffs[length(diffs)])
    value1 <- s[c(1,diffs+1)]
    cat("", "Sequence Length Encoding\n", " lengths:")
    str(lengths)
    cat("  value1:")
    str(value1)
}


sle(s)
 Sequence Length Encoding
  lengths: int [1:4] 5 1 1 5
  value1: num [1:4] 1 5 5 5

sle(c(2,4,1:4,rep(5,4),6:9,4,4,4))
 Sequence Length Encoding
  lengths: int [1:9] 1 1 5 1 1 5 1 1 1
  value1: num [1:9] 2 4 1 5 5 5 4 4 4

答案 4 :(得分:3)

这是对Joris Meys解决方案的增强。考虑这是解决未来问题的方法:-)。

卡尔

seqle <- function(x,incr=1) {
    if(!is.numeric(x)) x <- as.numeric(x)
    n <- length(x)
    #y <- x[-1L] != x[-n] + 1L
    y <- x[-1L] != x[-n] + incr
    i <- c(which(y|is.na(y)),n)
    list( lengths = diff(c(0L,i)),  values = x[head(c(0L,i)+1L,-1L)])
}

答案 5 :(得分:0)

“我的用例是我正在使用SPSS导出文件中的调查数据。问题网格中的每个子问题都会有一个模式粘贴的名称(”q“,1:5),但有时会有一个“其他”类别,将标记为q_99,q_other或其他。我希望找到一种识别序列的方法。“

当我从确认,DASH,SPSS,SAS,MySQL或其他任何东西中提取数据时,我通常会做这样的事情,因为它总是会受到数据的限制。():

surv.pull <- function(dat, pattern) {
  dat <- data.frame(dat[,grep(pattern,colnames(dat))],check.names=F)
return(dat)
}

如果您使用pattern之类[q][_][9][9],则可以决定是否通过添加“。”来提取其他数据空间的data.frame。到最后[q][_][9][9].,以便它拉q_99whatever

我的大多数数据列都是这样的形式,如q8a.1,.3,.4,.5,.6,.7,.8,......所以surv.pull(dat, "[q][8][a].")会将它们全部拉出来,包括另一个如果有指定。显然,使用正则表达式可以决定是否拉另一个。

或者,一般惯例是将其他指定问题推送到数据空间的末尾,因此快速df <- df[-ncol(df)]会丢弃它,或other_list <- df[ncol(df)]会保存它。