在R中的每一行数据table中寻找数字序列的存在
Look for existence of number sequence in every row of data table in R
我正在寻找 return 数据 table 的逻辑,其中应用一个函数来确定该行中是否存在特定的数字序列,而不管每个元素的长度那个序列。
例如在 c(1,1,1,3,3,2,2,2,2,2,1) 我感兴趣的是 c(1,3,2) 是否按该顺序存在。指定序列的每个元素有多长并不重要。首先使用 rle
,然后使用 this post 中用户定义的 "%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
所以,我想对数据 table 做同样的事情,针对数据 table.[= 的每一行查找特定序列,而不考虑每个元素的长度16=]
# 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 行应遵循指定的顺序并且 return 正确。
如果有办法降低 %seq_in%,我完全赞成!!
你可以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
您可以尝试 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
一个选项也是使用 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
参考:
我正在寻找 return 数据 table 的逻辑,其中应用一个函数来确定该行中是否存在特定的数字序列,而不管每个元素的长度那个序列。
例如在 c(1,1,1,3,3,2,2,2,2,2,1) 我感兴趣的是 c(1,3,2) 是否按该顺序存在。指定序列的每个元素有多长并不重要。首先使用 rle
,然后使用 this post 中用户定义的 "%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
所以,我想对数据 table 做同样的事情,针对数据 table.[= 的每一行查找特定序列,而不考虑每个元素的长度16=]
# 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 行应遵循指定的顺序并且 return 正确。
如果有办法降低 %seq_in%,我完全赞成!!
你可以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
您可以尝试 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
一个选项也是使用 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
参考: