r-将一组视为两组,因为行分裂



让我们假设我有数据框架

df <- data.frame(a = c(rep("a", 5), rep("b", 5), rep("a", 5)), 
                 b = c(rep(1, 2), rep(2, 5), rep(1, 8)))
> df
   a b
1  a 1
2  a 1
3  a 2
4  a 2
5  a 2
6  b 2
7  b 2
8  b 1
9  b 1
10 b 1
11 a 1
12 a 1
13 a 1
14 a 1
15 a 1

我想按ab对数据进行分组,并在第三列中命名该组(数字(,但我对我来说是新组是具有上述其他组的值。因此,我有组a1a2 b2b1a1。我想将第二个a1视为新组。因此,结果应该是:

   a b group
1  a 1 1
2  a 1 1
3  a 2 2
4  a 2 2
5  a 2 2
6  b 2 3
7  b 2 3
8  b 1 4
9  b 1 4
10 b 1 4
11 a 1 5
12 a 1 5
13 a 1 5
14 a 1 5
15 a 1 5

我唯一可以做的方法是使用循环:

group <- numeric(nrow(df))
value <- 1
for (i in 1:nrow(df)) {
    if (i == 1) {
        group[i] <- value
    } else {
        if (all(df$a[i] == df$a[i - 1], 
                df$b[i] == df$b[i - 1])) {
            group[i] <- value
        } else {
            value <- value + 1
            group[i] <- value
        }
    }
}
df$group <- group
df

但是这个解决方案不是很聪明。我可以使用dplyr或不循环做类似的事情吗?

尝试:

df <- data.frame(a = c(rep("a", 5), rep("b", 5), rep("a", 5)), 
                 b = c(rep(1, 2), rep(2, 5), rep(1, 8)))
library(dplyr)
transmute(df,a,b,group=cumsum(ifelse(lag(a)!=a | lag(b)!=b | is.na(lag(a)),1,0)))

或:

mutate(df,group=cumsum(ifelse(lag(a)!=a | lag(b)!=b | is.na(lag(a)),1,0)))

您可以在tidyrrle中使用unite

library(dplyr);library(tidyr)
df%>%
unite("a_b",a,b,remove=FALSE)%>%
mutate(group = {sq = rle(a_b); rep(seq_along(sq$lengths), sq$lengths)})
   a_b a b group
1  a_1 a 1     1
2  a_1 a 1     1
3  a_2 a 2     2
4  a_2 a 2     2
5  a_2 a 2     2
6  b_2 b 2     3
7  b_2 b 2     3
8  b_1 b 1     4
9  b_1 b 1     4
10 b_1 b 1     4
11 a_1 a 1     5
12 a_1 a 1     5
13 a_1 a 1     5
14 a_1 a 1     5
15 a_1 a 1     5

您可以使用dplyr::group_indices获取一系列组ID

gi <- group_indices(df, a, b)
gi
# [1] 1 1 2 2 2 4 4 3 3 3 1 1 1 1 1

,然后只添加到这些组ID中的cummax

ids <- cummax(gi) + gi
ids 
# [1] 2 2 4 4 4 8 8 7 7 7 5 5 5 5 5

它们不完全像您所需的输出中,但可以在必要时进行重新标记。他们将以任何方式作为小组索引工作。

最新更新