识别出现

时间:2017-08-07 18:40:22

标签: r subsequence

考虑以下数据集:

set.seed(50)
d = matrix(rbinom(1000, 1, 0.9), ncol = 20)

每行对应一个对象,每列对应一个 测量物体。例如,行可以是a中的个体 研究和专栏可以通过时间重复测量。在这 例如,测量值为TRUE / FALSE表示存在或不存在 对象

我正在寻找一种能让我识别出来的算法 具有n重合观测值的行的最大集合。 换句话说,我正在寻找一种过滤所有行的方法 在同一列中有n个TRUE值。该组的成员可以 但有超过n个真值。

简单示例:具有20(全部)TRUE值的行由

捕获
which(apply(d, 1, all))

标识行3, 10, 12, 24, 36, 39, 48, 50。同样,它是 易于识别所有独特序列并识别共享的组 同样的观察:

unique.series = d[which(!duplicated(d)),]
groups = vector("list", nrow(unique.series))
for(i in seq_along(groups))
  groups[[i]] = which(apply(d, 1, function(x) 
    identical(x, unique.series[i,])))

但是,如果我希望所有群体观察到19个或更多,该怎么办?例如, 群组3(行3, 10, 12, 24, 36, 39, 48, 50)和21 (行23, 32, 40)仅因观察9而异 (第3组有观察,但组21没有)。我怎么能够 以编程方式识别部分匹配的系列,即包含一些 匹配观测的子集?这似乎是一个子序列匹配 问题,但它更抽象,因为子序列不需要是连续的。

一种方法可能是使用正则表达式,但我不能让它工作 右:

unique.strings = lapply(
apply(unique.series, 1, function(x) 
    which(as.logical(x))),
  paste,
  collapse = ","
)
reg.strings = paste0("^", lapply(
  apply(unique.series, 1, function(x) 
    sprintf("(%d)", which(as.logical(x)))), 
  paste, collapse = "+(,[0-9],)*"), "$")  
lapply(unique.strings, grep, x =  unique.strings) # NOT CORRECT

我会很感激任何替代算法,基于正则表达式或其他算法。

1 个答案:

答案 0 :(得分:0)

这不是一个完整的答案,但我确实得到了一半以上。我放弃了正则表达式方法而是 采用二元矩阵方法。

将在事件中表示重合观察的集合 矩阵作为TRUE值的块。我不需要那个 观察是连续的,即行的/列排序 矩阵无所谓。因此,我可以简单地重新排列我的矩阵 这些事件按块分组,然后使用块检测 或聚类算法以提取观察集。那里有两个 此过程的组件:首先,重新排列矩阵以使其成为 通过列/行交换尽可能“阻塞”。第二,确定 排列矩阵中的块。

安排部分实际上非常简单。我用了seriation 打包将矩阵重新排列成块。

set.seed(50)
d = matrix(as.logical(rbinom(50, 1, 0.75)), ncol = 10)
rownames(d) = LETTERS[1:5]   # individual IDs
colnames(d) = month.abb[1:10]

library(seriation)
o = seriate(d)
d.a = permute(d, o)            # rearranged matrix

我还没有为块检测确定一个好方法,但有几个SO问题涉及最大块检测(例如12)。我希望我能够调整这些算法来找到最大的宽度 n 或类似的东西。如果我找到一个好的解决方案,我会更新这个答案。