我希望返回一个逻辑到数据表,其中应用了一个函数,该函数确定在行中是否存在特定的数字序列,而不管该序列的每个元素的长度。
。在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
参考:- 获取一个数字向量在另一个向量中的索引