是否有等同于 data.table::rleid 的 dplyr?
Is there a dplyr equivalent to data.table::rleid?
data.table
提供了一个很好的便利函数,rleid
用于 运行-length 编码:
library(data.table)
DT = data.table(grp=rep(c("A", "B", "C", "A", "B"), c(2, 2, 3, 1, 2)), value=1:10)
rleid(DT$grp)
# [1] 1 1 2 2 3 3 3 4 5 5
我可以在基础 R
中模仿这个:
df <- data.frame(DT)
rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths)
# [1] 1 1 2 2 3 3 3 4 5 5
有谁知道 dplyr
等效项(?)或者 "best" 使用 dplyr
创建 rleid
行为的方法是执行以下操作
library(dplyr)
my_rleid = rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths)
df %>%
mutate(rleid = my_rleid)
你可以这样做(当你有两个 data.table and dplyr 加载):
DT <- DT %>% mutate(rlid = rleid(grp))
这给出:
> DT
grp value rlid
1: A 1 1
2: A 2 1
3: B 3 2
4: B 4 2
5: C 5 3
6: C 6 3
7: C 7 3
8: A 8 4
9: B 9 5
10: B 10 5
当你不想单独加载data.table时你也可以使用(正如@DavidArenburg在评论中提到的):
DT <- DT %>% mutate(rlid = data.table::rleid(grp))
正如@RichardScriven 在他的 中所说,您可以 copy/steal 它:
myrleid <- data.table::rleid
如果你只想使用基础 R 和 dplyr,更好的方法是将你自己的 rleid()
的一两行版本包装成一个函数,并且然后在需要时应用它。
library(dplyr)
myrleid <- function(x) {
x <- rle(x)$lengths
rep(seq_along(x), times=x)
}
## Try it out
DT <- DT %>% mutate(rlid = myrleid(grp))
DT
# grp value rlid
# 1: A 1 1
# 2: A 2 1
# 3: B 3 2
# 4: B 4 2
# 5: C 5 3
# 6: C 6 3
# 7: C 7 3
# 8: A 8 4
# 9: B 9 5
#10: B 10 5
您可以使用 dplyr
中的 lag
函数来完成。
DT <-
DT %>%
mutate(rleid = (grp != lag(grp, 1, default = "asdf"))) %>%
mutate(rleid = cumsum(rleid))
给予
> DT
grp value rleid
1: A 1 1
2: A 2 1
3: B 3 2
4: B 4 2
5: C 5 3
6: C 6 3
7: C 7 3
8: A 8 4
9: B 9 5
10: B 10 5
OP 使用的方法的简化(不涉及额外的包)可以是:
DT %>%
mutate(rleid = with(rle(grp), rep(seq_along(lengths), lengths)))
grp value rleid
1 A 1 1
2 A 2 1
3 B 3 2
4 B 4 2
5 C 5 3
6 C 6 3
7 C 7 3
8 A 8 4
9 B 9 5
10 B 10 5
或者:
DT %>%
mutate(rleid = rep(seq(ls <- rle(grp)$lengths), ls))
data.table
提供了一个很好的便利函数,rleid
用于 运行-length 编码:
library(data.table)
DT = data.table(grp=rep(c("A", "B", "C", "A", "B"), c(2, 2, 3, 1, 2)), value=1:10)
rleid(DT$grp)
# [1] 1 1 2 2 3 3 3 4 5 5
我可以在基础 R
中模仿这个:
df <- data.frame(DT)
rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths)
# [1] 1 1 2 2 3 3 3 4 5 5
有谁知道 dplyr
等效项(?)或者 "best" 使用 dplyr
创建 rleid
行为的方法是执行以下操作
library(dplyr)
my_rleid = rep(seq_along(rle(df$grp)$values), times = rle(df$grp)$lengths)
df %>%
mutate(rleid = my_rleid)
你可以这样做(当你有两个 data.table and dplyr 加载):
DT <- DT %>% mutate(rlid = rleid(grp))
这给出:
> DT grp value rlid 1: A 1 1 2: A 2 1 3: B 3 2 4: B 4 2 5: C 5 3 6: C 6 3 7: C 7 3 8: A 8 4 9: B 9 5 10: B 10 5
当你不想单独加载data.table时你也可以使用(正如@DavidArenburg在评论中提到的):
DT <- DT %>% mutate(rlid = data.table::rleid(grp))
正如@RichardScriven 在他的
myrleid <- data.table::rleid
如果你只想使用基础 R 和 dplyr,更好的方法是将你自己的 rleid()
的一两行版本包装成一个函数,并且然后在需要时应用它。
library(dplyr)
myrleid <- function(x) {
x <- rle(x)$lengths
rep(seq_along(x), times=x)
}
## Try it out
DT <- DT %>% mutate(rlid = myrleid(grp))
DT
# grp value rlid
# 1: A 1 1
# 2: A 2 1
# 3: B 3 2
# 4: B 4 2
# 5: C 5 3
# 6: C 6 3
# 7: C 7 3
# 8: A 8 4
# 9: B 9 5
#10: B 10 5
您可以使用 dplyr
中的 lag
函数来完成。
DT <-
DT %>%
mutate(rleid = (grp != lag(grp, 1, default = "asdf"))) %>%
mutate(rleid = cumsum(rleid))
给予
> DT
grp value rleid
1: A 1 1
2: A 2 1
3: B 3 2
4: B 4 2
5: C 5 3
6: C 6 3
7: C 7 3
8: A 8 4
9: B 9 5
10: B 10 5
OP 使用的方法的简化(不涉及额外的包)可以是:
DT %>%
mutate(rleid = with(rle(grp), rep(seq_along(lengths), lengths)))
grp value rleid
1 A 1 1
2 A 2 1
3 B 3 2
4 B 4 2
5 C 5 3
6 C 6 3
7 C 7 3
8 A 8 4
9 B 9 5
10 B 10 5
或者:
DT %>%
mutate(rleid = rep(seq(ls <- rle(grp)$lengths), ls))