让我们假设我有数据框架
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
我想按a
和b
对数据进行分组,并在第三列中命名该组(数字(,但我对我来说是新组是具有上述其他组的值。因此,我有组a1
,a2
b2
,b1
和a1
。我想将第二个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)))
您可以在tidyr
和rle
中使用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
它们不完全像您所需的输出中,但可以在必要时进行重新标记。他们将以任何方式作为小组索引工作。