【问题标题】:How to count the number of two observations binary combinations?如何计算两个观察值二进制组合的数量?
【发布时间】:2017-01-09 19:00:10
【问题描述】:

在下面的示例中,我想知道010 序列的数量,或1010 序列的数量。下面是一个可行的例子;

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

在本例中,010 序列的数量为 6,1010 序列的数量为 4。

计算连续序列数的最有效/最简单的方法是什么?

【问题讨论】:

  • 这适用于第一种情况sum(diff(diff(x)) == -2),但有人可以检查它是否在任何地方失败。

标签: r count


【解决方案1】:

无绳方式:

f = function(x, patt){
  if (length(x) == length(patt)) return(as.integer(x == patt))
  w = head(seq_along(x), 1L-length(patt))
  for (k in seq_along(patt)) w <- w[ x[w + k - 1L] == patt[k] ]
  w
}

length(f(x, patt = c(0,1,0))) # 6
length(f(x, patt = c(1,0,1,0))) # 4

替代方案。来自@cryo11,这是另一种方式:

function(x,patt) sum(apply(embed(x,length(patt)),1,function(x) all(!xor(x,patt))))

或其他变体:

function(x,patt) sum(!colSums( xor(patt, t(embed(x,length(patt)))) ))

或使用 data.table:

library(data.table)
setkey(setDT(shift(x, seq_along(patt), type = "lead")))[as.list(patt), .N]

shift 函数与embed 非常相似。)

【讨论】:

  • +1 表示“无字符串”方式。这里还有一个:f=function(x,patt) sum(apply(embed(x,length(patt)),1,function(x) all(!xor(x,patt))))。这个不需要外层length
  • @cryo111 很酷,从来没想过要使用异或!我想还有一些方法可以将embed==、转置/扫描以及列或行总和一起使用。
【解决方案2】:

另一种解决方案是:

library(stringr)
x <- c(1,0,0,1,0,0,0,1,1,1,0,0,1,0,1,0,1,0,1,0,1,0)
xx = paste0(x, collapse = "")
str_count(xx, '(?<=010)')
[1] 6

str_count(xx, '(?<=1010)')
[1] 4

正如@Pierre Lafortune 在 cmets 中指出的那样,这可以在不使用任何包的情况下完成:

length(gregexpr("(?<=010)", xx, perl=TRUE)[[1]])
[1] 6

【讨论】:

  • 嘿,这太酷了!!我想我需要尽快学习这个包! :) 我正忙着尝试使用 base R
  • 是的,两种情况下的输出都不正确。我认为代码正在向前滚动,并没有考虑到所有的观察结果。例如“1010”的答案应该是 4。
  • 优秀,除了第二个(“1010”)有一个额外的'它不需要
  • 无需复杂的设置length(gregexpr("(?&lt;=010)", xx, perl=TRUE)[[1]])
  • 也不需要任何软件包。
【解决方案3】:

逻辑:取你正在搜索的模式长度的子串,并将其与模式进行比较。

xx = paste0(x, collapse = "")
# [1] "1001000111001010101010"
# case 1 :
xxx = "010"
sum(sapply(1:(length(x)-nchar(xxx)+1), function(i) substr(xx,i,i+nchar(xxx)-1)==xxx))
# [1] 6

# case 2 :
xxx = "1010"
# [1] 4

【讨论】:

    【解决方案4】:

    R 在 3.3.0 中引入了startsWith 函数。使用这个和substring,我们可以将@joel.wilson的方法实现为

    sum(startsWith(substring(paste(x, collapse=""),
                             head(seq_along(x), -2), tail(seq_along(x), -2)), "010"))
    

    这里,substring 构造所有三个字符相邻集,startsWith 测试每个字符是否与“010”相同。然后将 TRUE 值相加。

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2018-01-12
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多