r语言 - 根据连续的 TRUE/FALSE 列值添加分组编号



给定此数据框:

library(dplyr)
dat <- data.frame(
bar = c(letters[1:10]),
foo = c(1,2,3,5,8,9,11,13,14,15)
)
bar foo
1    a   1
2    b   2
3    c   3
4    d   5
5    e   8
6    f   9
7    g  11
8    h  13
9    i  14
10   j  15

我首先要确定组,如果foo数字是连续的:

dat <- dat %>% mutate(in_cluster = 
ifelse( lead(foo) == foo +1 | lag(foo) == foo -1, 
TRUE, 
FALSE))

这将导致以下数据框:

bar foo in_cluster
1    a   1       TRUE
2    b   2       TRUE
3    c   3       TRUE
4    d   5      FALSE
5    e   8       TRUE
6    f   9       TRUE
7    g  11      FALSE
8    h  13       TRUE
9    i  14       TRUE
10   j  15       TRUE

可以看出,值1,2,3形成一个组,然后值5是独立的,不属于一个集群,然后值8,9形成另一个集群,依此类推。

我想将集群编号添加到这些"组"中。

预期产出:

bar foo in_cluster cluster_number
1    a   1       TRUE              1
2    b   2       TRUE              1
3    c   3       TRUE              1
4    d   5      FALSE             NA
5    e   8       TRUE              2
6    f   9       TRUE              2
7    g  11      FALSE             NA
8    h  13       TRUE              3
9    i  14       TRUE              3
10   j  15       TRUE              3

对于这样的事情,可能有更好的tidverse方法。例如,如果in_cluster是通过任意长度case_when定义的,则可以使用group_indices。但是,我们也可以使用rle函数实现我们自己的方法来专门处理逻辑值运行长度。

解决方案 1(R 版本> 3.5)

lgl_indices <- function(var){
x <- rle(var)
cumsum(x[[2]]) |> ((.){ .[which(!x[[2]], T)] <- NA ; .})() |> rep(x[[1]])
}

解决方案 2

lgl_indices <- function(var){
x <- rle(var)
y <- cumsum(x$values)
y[which(x$values == F)] <- NA
rep(y, x$lengths)
}

解决方案 3

lgl_indices <- function(var){
x <- rle(var)
l <- vector("list", length(x))
n <- 1L
for (i in seq_along(x[[1]])) {
if(!x$values[i]) grp <- NA else {
grp <- n
n <- n + 1L
}
l[[i]] <- rep(grp, x$lengths[i])
}
Reduce(c, l)
}
dat %>%
mutate(cluster_number = lgl_indices(in_cluster))
bar foo in_cluster cluster_number
1   a   1       TRUE              1
2   b   2       TRUE              1
3   c   3       TRUE              1
4   d   5      FALSE             NA
5   e   8       TRUE              2
6   f   9       TRUE              2

这可能不是有效的方法。尽管如此,这仍然有效:

# Cumuative sum of the logical
dat$new_cluster <- cumsum(!dat$in_cluster)+1
# using the in_cluster to subset and replacing the cluster number for FALSE by NA
dat[!dat$in_cluster,]$new_cluster <- NA
dat
bar foo in_cluster new_cluster
1   a   1       TRUE           1
2   b   2       TRUE           1
3   c   3       TRUE           1
4   d   5      FALSE          NA
5   e   8       TRUE           2
6   f   9       TRUE           2

相关内容

最新更新