查找r中每一行数据表中是否存在数字序列



我希望返回一个逻辑到数据表,其中应用了一个函数,该函数确定在行中是否存在特定的数字序列,而不管该序列的每个元素的长度。

。在c(1,1,1,3,3,2,2,2,2,2,2,1)中,我感兴趣的是c(1,3,2)是否以这个顺序存在。指定序列的每个元素有多长并不重要。首先使用本文中用户定义的rle,然后使用"%seq_in%",我们可以执行以下操作:

# this function searches for a specific vector in order in another vector
"%seq_in%" = function(b,a) any(sapply(1:(length(a)-length(b)+1),function(i) all(a[i:(i+length(b)-1)]==b)))
v1 <- c(1,1,1,3,3,2,2,2,2,2,1)
c(1,3,2) %seq_in% rle(v1)$values
[1] TRUE
# for clarity
c(1,2,3) %seq_in% rle(v1)$values
[1] FALSE

所以,我想对数据表做同样的事情,寻找一个特定的序列,不管每个元素的长度,对数据表的每一行。

# dummy data
dt_dummy <- data.table(A = c(2,2,3,3,1),B = c(3,2,2,1,3), C = c(2,2,3,3,1), D = c(2,3,2,2,3), 
E = c(2,3,2,1,1), F = c(2,2,2,1,3), G = c(3,2,3,2,2), H = c(2,3,1,2,2))
dt_dummy
   A B C D E F G H
1: 2 3 2 2 2 2 3 2
2: 2 2 2 3 3 2 2 3
3: 3 2 3 2 2 2 3 1
4: 3 1 3 2 1 1 2 2
5: 1 3 1 3 1 3 2 2
# define simple function to return the values from rle
f1 <- function(v){  
 v1 <- unlist(rle(v)$values)
 return(v1)
}
# apply to every row of dt
dt_dummy[, GCG_Rot := c(3,2,3) %seq_in% f1(dt_dummy), by = seq_len(nrow(dt_dummy))]

我似乎无法让函数工作,其中生成的列是TRUE或FALSE

第1、2行,&3应遵循指定的顺序并返回TRUE。

如果有办法减少%seq_in%,我完全赞成!!

您可以尝试unlist而不是.SD,例如

> dt_dummy[, GCG_RoT := c(3, 2, 3) %seq_in% f1(unlist(.SD)), seq(nrow(dt_dummy))][]
   A B C D E F G H GCG_RoT
1: 2 3 2 2 2 2 3 2    TRUE
2: 2 2 2 3 3 2 2 3    TRUE
3: 3 2 3 2 2 2 3 1    TRUE
4: 3 1 3 2 1 1 2 2   FALSE
5: 1 3 1 3 1 3 2 2   FALSE

此外,您可以像下面这样定义函数f(不需要%seq_in% + f1)

> f <- function(a, b) grepl(toString(a), toString(rle(b)$values))
> dt_dummy[, GCG_RoT := f(c(3, 2, 3), unlist(.SD)), seq(nrow(dt_dummy))][]
   A B C D E F G H GCG_RoT
1: 2 3 2 2 2 2 3 2    TRUE
2: 2 2 2 3 3 2 2 3    TRUE
3: 3 2 3 2 2 2 3 1    TRUE
4: 3 1 3 2 1 1 2 2   FALSE
5: 1 3 1 3 1 3 2 2   FALSE

您可以为每一行apply一个函数

dt_dummy[, GCG_Rot := apply(.SD,1, function(x) c(3,2,3) %seq_in% rle(x)$values)]
#    A B C D E F G H GCG_RoT
# 1: 2 3 2 2 2 2 3 2    TRUE
# 2: 2 2 2 3 3 2 2 3    TRUE
# 3: 3 2 3 2 2 2 3 1    TRUE
# 4: 3 1 3 2 1 1 2 2   FALSE
# 5: 1 3 1 3 1 3 2 2   FALSE

也可以选择从collapse使用dapply

library(data.table)
library(collapse)
dt_dummy[, GCG_RoT := dapply(.SD, MARGIN = 1, function(x) c(3, 2, 3) %seq_in% f1(x))]

与产出

 dt_dummy
   A B C D E F G H GCG_RoT
1: 2 3 2 2 2 2 3 2    TRUE
2: 2 2 2 3 3 2 2 3    TRUE
3: 3 2 3 2 2 2 3 1    TRUE
4: 3 1 3 2 1 1 2 2   FALSE
5: 1 3 1 3 1 3 2 2   FALSE

这里有另一个选项,我认为应该更快:

#see reference 1
fseqin <- function(x, v) {
    w = seq_along(v)
    for (i in seq_along(x)) {
        w = w[v[w+i-1L] == x[i]]
        if (length(w)==0L || is.na(w)) return(FALSE)
    }
    TRUE
} #fseqin

m <- as.matrix(dt_dummy)
dt_dummy[, found := 
    data.table(row=as.vector(row(m)), col=as.vector(col(m)), v=as.vector(m))[
        order(row, col)][
            !duplicated(rleid(row, v)), fseqin(c(3,2,3), v), row]$V1
]

输出:

   A B C D E F G H found
1: 2 3 2 2 2 2 3 2  TRUE
2: 2 2 2 3 3 2 2 3  TRUE
3: 3 2 3 2 2 2 3 1  TRUE
4: 3 1 3 2 1 1 2 2 FALSE
5: 1 3 1 3 1 3 2 2 FALSE

参考:

  1. 获取一个数字向量在另一个向量中的索引

最新更新