给定0-1序列中大小为3的所有子序列的频率?

时间:2010-02-17 07:22:29

标签: r count sequence

给定数据

s<-c(1,0,0,0,1,0,0,0,0,0,1,1,1,0,0)

我可以用table或ftable计算1和0

ftable(s,row.vars =1:1)

和11s,01s,10s,00s的总数发生在带有

的s中
table(s[-length(s)],s[-1]).

计算111s,011s,...,100s,000s的出现次数的聪明方法是什么?理想情况下,我想要一个计数表x,如

   0 1
11 x x
01 x x
10 x x
00 x x

是否有一般方法计算长度为k = 1,2,3,4,...的所有可能子序列的总出现次数?

2 个答案:

答案 0 :(得分:5)

嗯,好像你首先需要从你的向量生成n元组。以下功能应该实现:

makeTuples <- function( x, n ){

  # Very inefficient way to loop... but what the heck
  tuples <- list()

  for( i in 1:n ){

    tuples[[i]] <- x[i:(length(x)-n+i)]

  }

  return(tuples)

}

然后,您可以使用makeTuples()table()的结果提供给do.call()

do.call( table, makeTuples(s,3) )

, ,  = 0


    0 1
  0 4 1
  1 3 1

, ,  = 1


    0 1
  0 2 1
  1 0 1

这是有效的,因为makeTuples()函数将元组作为列表列表返回。输出不是你想要的那么好,但是你可以编写一个重新格式化的函数,比如说:

, ,  = 0


    0 1
  0 4 1
  1 3 1

要:

     0 1
  00 4 1
  01 3 1

它需要在table返回的n维数组的外部n-2维上循环,创建行名并将事物连接在一起。

  

<强>更新

所以,我只是坐在一个随机过程类中,当我想出一个或多或少直接的方式来产生你想要的输出而不试图解开table()的输出。首先,您需要一个能够从您的人口中生成n个选择的所有可能排列的函数。排列的产生可以用expand.grid()来完成,但它需要一点糖涂层:

permute <- function( population, n ){

  permutations <- do.call( expand.grid, rep( list(population), n ) )

  permutations <- apply( permutations, 1, paste, collapse = '' )

  return( permutations )

}

基本思想是遍历排列列表并计算与给定排列匹配的元组数。由于您希望将结果拆分为表格,因此我们应该从总体中选择n-1个元素的排列,并让最后一个位置构成表格的列。这是一个函数,它采用大小为n-1的排列,一个元组列表,以及从中抽取元组的总体,并生成一个匹配计数的命名向量:

countFrequency <- function(permutation,tuples,population){

  permutations <- paste( permutation, population, sep = '' )

  # Inner lapply applies the equality operator `==` to each
  # permutation and returns a list of TRUE/FALSE vectors.
  # Outer lapply sums the number of TRUE values in each vector. 
  frequencies <- lapply(lapply(permutations,`==`,tuples),sum)

  names( frequencies ) <- as.character( population )

  return( unlist(frequencies) )

}

最后,所有三个函数都可以组合成一个更大的函数,它接受一个向量,将它分成n元组并返回一个频率表。最后的聚合操作是使用Hadley Wickham的ldply()包中的plyr完成的,因为它可以很好地保存信息,例如哪个排列对应于哪一行输出匹配:

permutationFrequency <- function( vector, n, population = unique( vector ) ){

  # Split the vector into tuples.
  tuples <- makeTuples( vector, n )

  # Coerce and compact the tuples to a vector of strings.
  tuples <- do.call(cbind,tuples)
  tuples <- apply( tuples, 1, paste, collapse = '' )

  # Generate permutations of n-1 elements from the population.
  # Turn into a named list for ldply() to work it's magic.
  permutations <- permute( population, n-1 )
  names( permutations ) <- permutations

  frequencies <- ldply( permutations, countFrequency,
    tuples = tuples, population = population )

  return( frequencies )

}

然后你去了:

require( plyr )
permutationFrequency( s, 2 )
  .id 1 0
1   1 2 3
2   0 2 7

permutationFrequency( s, 3 )
  .id 1 0
1  11 1 1
2  01 1 1
3  10 0 3
4  00 2 4

permutationFrequency( s, 4 )
  .id 1 0
1 111 0 1
2 011 1 0
3 101 0 0
4 001 1 1
5 110 0 1
6 010 0 1
7 100 0 2
8 000 2 2

permutationFrequency( sample( -1:1, 10, replace = T ), 2 )
  .id 1 -1 0
1   1 1  2 0
2  -1 0  1 2
3   0 1  0 2

向我的随机过程老师道歉,但R中的函数式编程问题比今天的Gambler's Ruin更有趣......

答案 1 :(得分:1)

一种方法是创建子序列的数据框,然后使用表函数:

s<-c(1,0,0,0,1,0,0,0,0,0,1,1,1,0,0)
n<-length(s)
k<-3
subseqs<-t(sapply(1:(n-k+1),function(i){s[i:(i+k-1)]}))
colnames(subseqs)<-paste('Y',1:k,sep="")
subseqs<-data.frame(subseqs)
table(subseqs)

这会产生

, , Y3 = 0

   Y2
Y1  0 1
  0 4 1
  1 3 1

, , Y3 = 1

   Y2
Y1  0 1
  0 2 1
  1 0 1

使用ftable代替table或在table的输出上使用类似于问题的显示:

ftable(subseqs)
          Y3 0 1
    Y1 Y2       
    0  0     4 2
       1     1 1
    1  0     3 0
       1     1 1