在二进制列中寻找模式

我需要找到并计算3个或多个连续零后以1出现的ID。

这是我所拥有的一个例子:

#  ID   Jan  Feb Mar  Apr May Jun Jul Aug Sept Oct
#   1   0    0   0    1   0   0   1   1    1    0
#   2   0    0   0    0   0   0   1   0    0    0
#   3   0    0   0    0   0   0   0   0    0    1
#   4   1    0   0    1   0   1   0   1    0    1
#   5   0    0   1    0   0   1   1   0    0    1

c1<- c("ID","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct")
c2<-  c(1,1,0)
c3<- c(2,0)
c4<- c(3,1)
c5<- c(4,1)
c6<- c(5,1)
BD<-data.frame(rbind(c2,c3,c4,c5,c6))
colnames(BD)<-c1

我期望的结果是这样的:

#  ID   Jan  Feb Mar  Apr May Jun Jul Aug Sept Oct
#   1   0    0   0    1   0   0   1   1    1    0
#   2   0    0   0    0   0   0   1   0    0    1
#   3   0    0   0    0   0   0   0   0    0    1

有人知道怎么做吗?谢谢!

jinruien0219 回答:在二进制列中寻找模式

如果采用向量rowid(rleid(x))的{​​{1}},则每个元素的“运行”步数为*。您可以检查它是否> = 3并且元素为0。如果对于前一个元素(对于移位输出)为true,并且元素为1,则返回TRUE。然后检查该行中x个元素的真性。

any

*这是特定行(第一行)的示例

library(data.table)

rows <- 
  apply(BD,1,function(r) any(shift(rowid(rleid(r)) >= 3 & r == 0) & r == 1))

BD[rows,]
#    ID Jan Feb Mar Apr May Jun Jul Aug Sept Oct
# c2  1   0   0   0   1   0   0   1   1    1   0
# c3  2   0   0   0   0   0   0   1   0    0   0
# c4  3   0   0   0   0   0   0   0   0    0   1
,

您可以折叠成字符串,然后使用grep()搜索模式。

k <- 3

grep(sprintf(paste0("%0",k + 1,"d"),1),apply(d[-1],paste,collapse=""))
# [1] 2 4 5 6 8

如果不需要以下1,则可以使用rle()

d
#     id Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
# c1   1   1   1   0   1   1   0   0   1   1   1   0   0
# c2   2   0   0   0   1   1   1   0   1   1   0   1   0
# c3   3   1   0   0   1   1   0   1   1   1   0   1   0
# c4   4   0   0   0   0   0   1   1   0   0   1   1   0
# c5   5   0   0   0   1   1   1   1   0   0   1   0   1
# c6   6   1   0   0   0   1   0   1   0   0   0   0   1
# c7   7   0   1   0   0   1   0   1   1   1   0   0   1
# c8   8   0   1   1   1   1   1   1   1   0   0   0   1
# c9   9   0   1   0   0   1   1   0   0   1   1   1   0
# c10 10   1   1   0   1   0   1   1   0   0   1   0   1

k <- 3
d$id[sapply(as.data.frame(t(d[-1])),function(x) any(rle(x)$lengths[rle(x)$values == 0] >= k))]
# [1] 2 4 5 6 8

数据:

set.seed(0)
d <- data.frame(id=1:10,`dimnames<-`(matrix(sample(0:1,120,r=1),10),list(paste0("c",1:10),month.abb)))
,

您可以将行合并为字符串,并使用正则表达式匹配“ 0001”:

library(tidyverse)
rows = BD %>% 
  purrr::pmap(function(...) paste0(list(...)[-1],collapse='')) %>% 
  stringr::str_detect('0001')
BD[rows,]
,

这是可以实现的基本R解决方案

BDout <- subset(BD,apply(BD[-1],function(x) head(which(x==1),1))>3)

这样

> BDout
  ID Jan Feb Mar Apr May Jun Jul Aug Sept Oct
1  1   0   0   0   1   0   0   1   1    1   0
2  2   0   0   0   0   0   0   1   0    0   0
3  3   0   0   0   0   0   0   0   0    0   1
,

使用Numeric value: 755来融合和过滤符合条件的行的选项。

data.table

对于具有稀疏数据的大型数据集,它应该更快。

本文链接:https://www.f2er.com/2824583.html

大家都在问