使用dplyr按组获取累积计数

Reg*_*ton 3 r dplyr

提前致谢.我有以下数据:

df <- data.frame(person=c(1,1,1,1,2,2,2,2,3,3,3,3), 
             neighborhood=c("A","A","A","A","B","B","C","C","D","D","E","F"))
Run Code Online (Sandbox Code Playgroud)

我想生成一个新列,它给出了每个人在面板进行过程中所经过的邻域的累积计数.像这样:

df2 <- data.frame(person=c(1,1,1,1,2,2,2,2,3,3,3,3), 
             neighborhood=c("A","A","A","A","B","B","C","C","D","D","E","F"),
             moved=c(0,0,0,0,0,0,1,1,0,0,1,2)
             )
Run Code Online (Sandbox Code Playgroud)

再次感谢.

akr*_*run 5

我们可以按'人'使用组,然后通过match'邻域' 创建'移动' 及其unique值以获得索引并减去1.

df %>%
   group_by(person) %>% 
   mutate(moved = match(neighborhood, unique(neighborhood))-1)
#   person neighborhood moved
#    <dbl>       <fctr> <dbl>
#1       1            A     0
#2       1            A     0
#3       1            A     0
#4       1            A     0
#5       2            B     0
#6       2            B     0
#7       2            C     1
#8       2            C     1
#9       3            D     0
#10      3            D     0
#11      3            E     1
#12      3            F     2
Run Code Online (Sandbox Code Playgroud)

或者使用factor与levels指定为unique在"街区"值,强制为"整数"和减去1.

df %>%
   group_by(person) %>% 
   mutate(moved = as.integer(factor(neighborhood, levels = unique(neighborhood)))-1)
#   person neighborhood moved
#    <dbl>       <fctr> <dbl>
#1       1            A     0
#2       1            A     0
#3       1            A     0
#4       1            A     0
#5       2            B     0
#6       2            B     0
#7       2            C     1
#8       2            C     1
#9       3            D     0
#10      3            D     0
#11      3            E     1
#12      3            F     2
Run Code Online (Sandbox Code Playgroud)


h3r*_*m4n 5

这也可以通过包中rleid的frank功能或功能轻松实现data.table:

library(data.table)
# with 'rleid'
setDT(df)[, moved := rleid(neighborhood)-1, by = person]
# with 'frank'
setDT(df)[, moved := frank(neighborhood, ties.method='dense')-1, by = person]
Run Code Online (Sandbox Code Playgroud)

结果:

> df
    person neighborhood moved
 1:      1            A     0
 2:      1            A     0
 3:      1            A     0
 4:      1            A     0
 5:      2            B     0
 6:      2            B     0
 7:      2            C     1
 8:      2            C     1
 9:      3            D     0
10:      3            D     0
11:      3            E     1
12:      3            F     2
Run Code Online (Sandbox Code Playgroud)

有了dplyr可以使用的dense_rank功能:

library(dplyr)
df %>%
  group_by(person) %>%
  mutate(moved = dense_rank(neighborhood)-1)
Run Code Online (Sandbox Code Playgroud)