我想创建一个计算数字出现次数的计数器。 例如,假设我们有这样的数据
df <- data.frame(ID = c(rep(rep(seq(1:2),each=2),times=2)),gr=rep(c("A"),each=8))
ID gr
1 1 A
2 1 A
3 2 A
4 2 A
5 1 A
6 1 A
7 2 A
8 2 A
每当数据以2
结尾时,我想设置计数器。所以预期的产出
ID gr counter
1 1 A 1
2 1 A 1
3 2 A 1
4 2 A 1 ~~data ends with 2
5 1 A 2
6 1 A 2
7 2 A 2
8 2 A 2 ~~data ends with 2
1 A 3
1 A 3
2 A 3
2 A 3 @@just for an example
我试过这个
library(dplyr)
df%>%
group_by(gr)%>%
mutate(counter=cumsum(ID==2))
但它似乎甚至没有接近所需的输出!
我们怎么能这样做?
答案 0 :(得分:2)
有很多方法可以做到这一点。
df <- data.frame(ID = c(rep(rep(seq(1:2),each=2),times=4)), gr= "A")
您可以获取ID并查看其是增加还是减少。如果增加,请说这属于同一组。如果没有,请重置组(增加1)。
group <- rep(NA, length(df$ID))
group[1] <- 1
for (i in 2:length(df$ID)) {
if (df$ID[i] >= df$ID[i-1]) {
group[i] <- group[i-1]
} else {
group[i] <- group[i-1] + 1
}
}
df$group <- group
df
ID gr group
1 1 A 1
2 1 A 1
3 2 A 1
4 2 A 1
5 1 A 2
6 1 A 2
7 2 A 2
8 2 A 2
9 1 A 3
10 1 A 3
11 2 A 3
12 2 A 3
13 1 A 4
14 1 A 4
15 2 A 4
16 2 A 4
如果你对dplyr
感到害怕,你可以把它变成一个函数。
library(dplyr)
findIncrSeq <- function(x) {
group <- rep(NA, length(x))
group[1] <- 1
for (i in 2:length(x)) {
if (x[i] >= x[i-1]) {
group[i] <- group[i-1]
} else {
group[i] <- group[i-1] + 1
}
}
group
}
df %>%
group_by(gr) %>%
mutate(counter = findIncrSeq(ID))
# A tibble: 16 x 4
# Groups: gr [1]
ID gr group counter
<int> <fctr> <dbl> <dbl>
1 1 A 1 1
2 1 A 1 1
3 2 A 1 1
4 2 A 1 1
5 1 A 2 2
6 1 A 2 2
7 2 A 2 2
8 2 A 2 2
9 1 A 3 3
10 1 A 3 3
11 2 A 3 3
12 2 A 3 3
13 1 A 4 4
14 1 A 4 4
15 2 A 4 4
16 2 A 4 4
答案 1 :(得分:2)
dplyr
的选项:
# added one more row to your example
df <- data.frame(ID = c(rep(rep(seq(1:2),each=2),times=2),1),gr=rep(c("A"),each=9))
library(dplyr)
df %>%
group_by(gr) %>%
mutate(id=cumsum(c(0,diff(df$ID)) & lag(df$ID==2))+1)
输出:
# A tibble: 9 x 3
# Groups: gr [1]
ID gr id
<dbl> <fctr> <dbl>
1 1 A 1
2 1 A 1
3 2 A 1
4 2 A 1
5 1 A 2
6 1 A 2
7 2 A 2
8 2 A 2
9 1 A 3