根据行值

时间:2018-01-14 07:27:15

标签: r dplyr

我想创建一个计算数字出现次数的计数器。 例如,假设我们有这样的数据

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))

但它似乎甚至没有接近所需的输出!

我们怎么能这样做?

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