R 按连续出现的值分组

R 按连续出现的值分组,r,dplyr,R,Dplyr,我遇到了一个问题,迫使我使用一个循环,而不是我喜欢的dplyr管道流 我想根据相同值的连续观察结果对行进行分组。 例如,如果类型为a的前四个观察值相等,则前四个观察值应分配给同一组。排序问题,所以我不能dplyr::group_by和dplyr::summary 下面的代码应该可以很好地解释这个问题。我想知道是否有人能提出一种不那么冗长的方法来实现这一点,最好使用tidyverse包,而不是data.tables 由reprex包v0.2.1于2019-03-14创建 这种连续类型出现的分组实际

我遇到了一个问题,迫使我使用一个循环,而不是我喜欢的dplyr管道流

我想根据相同值的连续观察结果对行进行分组。 例如,如果类型为a的前四个观察值相等,则前四个观察值应分配给同一组。排序问题,所以我不能dplyr::group_by和dplyr::summary

下面的代码应该可以很好地解释这个问题。我想知道是否有人能提出一种不那么冗长的方法来实现这一点,最好使用tidyverse包,而不是data.tables

由reprex包v0.2.1于2019-03-14创建


这种连续类型出现的分组实际上只是一个中间步骤。我的最终目的是根据前一个concer_组中出现的val值,操纵给定concer_组的val。请提供相关套餐的建议。

您说没有数据表,但您确定吗?在这种情况下,它是如此的快速和简单

library(data.table)
setDT(df)[, groupid := rleid(type)][]

#     id type         val groupid
#  1:  1    a 0.624078793       1
#  2:  2    a 0.687361541       1
#  3:  3    a 0.817702740       1
#  4:  4    a 0.669857208       1
#  5:  5    a 0.100977936       1
#  6:  6    b 0.418275823       2
#  7:  7    b 0.660119857       2
#  8:  8    b 0.876015209       2
#  9:  9    b 0.473562143       2
# 10: 10    b 0.284474633       2
# 11: 11    a 0.034154862       3
# 12: 12    a 0.391760387       3
# 13: 13    a 0.383107868       3
# 14: 14    a 0.729583433       3
# 15: 15    a 0.006288375       3
# 16: 16    b 0.530179235       4
# 17: 17    b 0.802643704       4
# 18: 18    b 0.409618633       4
# 19: 19    b 0.309363642       4
# 20: 20    b 0.021918512       4
如果您坚持使用tidyverse/dplyr,当然您仍然可以使用 rleid功能如下:

df %>% mutate( groupid = data.table::rleid(type) )
基准 在更大的样本上

library(tidyverse)
library(data.table)

# Crete some large test data
df <- tibble(
  id = 1:200000,
  type = sample(letters[1:26], 200000, replace = TRUE),
  val = runif(200000)
)

dt <- as.data.table(df)

microbenchmark::microbenchmark(
  dplyr.rleid      = df %>% mutate( groupid = data.table::rleid(type) ),
  data.table.rleid = dt[, groupid := rleid(type)][], 
  rle = df %>% mutate(ID_rleid = {ID_rleid = rle(type); rep(seq_along(ID_rleid$lengths), ID_rleid$lengths)}),
  rle2 = df %>% mutate(ID_rleid = with(rle(type), rep(seq_along(lengths), lengths))),
  transform = transform(df, ID = with(rle(df$type), rep(seq_along(lengths), lengths))),
  times = 10)

# Unit: milliseconds
#             expr       min        lq      mean    median        uq        max neval
#      dplyr.rleid  3.153626  3.278049  3.410363  3.444949  3.502792   3.582626    10
# data.table.rleid  2.965639  3.065959  3.173992  3.145643  3.259672   3.507009    10
#              rle 13.059774 14.042797 24.364176 26.126176 29.460561  36.874054    10
#             rle2 12.641319 13.553846 30.951152 24.698338 34.139786 102.791719    10
#        transform 12.330717 22.419128 22.725242 25.532084 26.187634  26.702794    10

你说没有数据表,但你确定吗?在这种情况下,它是如此的快速和简单

library(data.table)
setDT(df)[, groupid := rleid(type)][]

#     id type         val groupid
#  1:  1    a 0.624078793       1
#  2:  2    a 0.687361541       1
#  3:  3    a 0.817702740       1
#  4:  4    a 0.669857208       1
#  5:  5    a 0.100977936       1
#  6:  6    b 0.418275823       2
#  7:  7    b 0.660119857       2
#  8:  8    b 0.876015209       2
#  9:  9    b 0.473562143       2
# 10: 10    b 0.284474633       2
# 11: 11    a 0.034154862       3
# 12: 12    a 0.391760387       3
# 13: 13    a 0.383107868       3
# 14: 14    a 0.729583433       3
# 15: 15    a 0.006288375       3
# 16: 16    b 0.530179235       4
# 17: 17    b 0.802643704       4
# 18: 18    b 0.409618633       4
# 19: 19    b 0.309363642       4
# 20: 20    b 0.021918512       4
如果您坚持使用tidyverse/dplyr,当然您仍然可以使用 rleid功能如下:

df %>% mutate( groupid = data.table::rleid(type) )
基准 在更大的样本上

library(tidyverse)
library(data.table)

# Crete some large test data
df <- tibble(
  id = 1:200000,
  type = sample(letters[1:26], 200000, replace = TRUE),
  val = runif(200000)
)

dt <- as.data.table(df)

microbenchmark::microbenchmark(
  dplyr.rleid      = df %>% mutate( groupid = data.table::rleid(type) ),
  data.table.rleid = dt[, groupid := rleid(type)][], 
  rle = df %>% mutate(ID_rleid = {ID_rleid = rle(type); rep(seq_along(ID_rleid$lengths), ID_rleid$lengths)}),
  rle2 = df %>% mutate(ID_rleid = with(rle(type), rep(seq_along(lengths), lengths))),
  transform = transform(df, ID = with(rle(df$type), rep(seq_along(lengths), lengths))),
  times = 10)

# Unit: milliseconds
#             expr       min        lq      mean    median        uq        max neval
#      dplyr.rleid  3.153626  3.278049  3.410363  3.444949  3.502792   3.582626    10
# data.table.rleid  2.965639  3.065959  3.173992  3.145643  3.259672   3.507009    10
#              rle 13.059774 14.042797 24.364176 26.126176 29.460561  36.874054    10
#             rle2 12.641319 13.553846 30.951152 24.698338 34.139786 102.791719    10
#        transform 12.330717 22.419128 22.725242 25.532084 26.187634  26.702794    10
您可以使用如下类似rleid的可能性:

df %>%
 mutate(ID_rleid = {ID_rleid = rle(type); rep(seq_along(ID_rleid$lengths), ID_rleid$lengths)})

      id type     val ID_rleid
   <int> <chr>  <dbl>    <int>
 1     1 a     0.0430        1
 2     2 a     0.858         1
 3     3 a     0.504         1
 4     4 a     0.318         1
 5     5 a     0.469         1
 6     6 b     0.144         2
 7     7 b     0.173         2
 8     8 b     0.0706        2
 9     9 b     0.958         2
10    10 b     0.557         2
11    11 a     0.358         3
12    12 a     0.973         3
13    13 a     0.982         3
14    14 a     0.177         3
15    15 a     0.599         3
16    16 b     0.627         4
17    17 b     0.454         4
18    18 b     0.682         4
19    19 b     0.690         4
20    20 b     0.713         4
您可以使用如下类似rleid的可能性:

df %>%
 mutate(ID_rleid = {ID_rleid = rle(type); rep(seq_along(ID_rleid$lengths), ID_rleid$lengths)})

      id type     val ID_rleid
   <int> <chr>  <dbl>    <int>
 1     1 a     0.0430        1
 2     2 a     0.858         1
 3     3 a     0.504         1
 4     4 a     0.318         1
 5     5 a     0.469         1
 6     6 b     0.144         2
 7     7 b     0.173         2
 8     8 b     0.0706        2
 9     9 b     0.958         2
10    10 b     0.557         2
11    11 a     0.358         3
12    12 a     0.973         3
13    13 a     0.982         3
14    14 a     0.177         3
15    15 a     0.599         3
16    16 b     0.627         4
17    17 b     0.454         4
18    18 b     0.682         4
19    19 b     0.690         4
20    20 b     0.713         4

使用RLEDF$type,repseq_alongles,Lengthsher的一篇文章,这几乎是一个骗局:@camille,这很接近,但这里的问题和答案更清楚。也许可以把这个问题当作这个问题的一个复制品来结束?如果使用RLEDF$type,repseq_alongles,Lengthsher的一篇文章,这几乎是一个复制品:@camille,这很接近,但这里的问题和答案更清楚。也许把这个问题当作这个问题的翻版来结束吧?你的论点很有说服力。我的理由是:a我还没有花时间学习data.tables,因为我天真地认为tidyverse满足了我的需求,而你可能已经说服了我。b我在做探索性分析,总有一天会有同事把我的工作翻译成python;我想让事情变得简单易懂,我的印象是DT比dplyr更难阅读。只需添加足够的注释,就像你在使用tidyverse时可能会做的那样。感谢你发布这篇文章:即使这不是提问者喜欢的解决方案,它也会对未来有同样问题的人有所帮助@djfinnoy看到答案底部的一种dplyr解决方案-谢谢虽然我说没有数据表,但我只是喜欢它的优雅;我会用额外的空间来评论你的论点。我的理由是:a我还没有花时间学习data.tables,因为我天真地认为tidyverse满足了我的需求,而你可能已经说服了我。b我在做探索性分析,总有一天会有同事把我的工作翻译成python;我想让事情变得简单易懂,我的印象是DT比dplyr更难阅读。只需添加足够的注释,就像你在使用tidyverse时可能会做的那样。感谢你发布这篇文章:即使这不是提问者喜欢的解决方案,它也会对未来有同样问题的人有所帮助@djfinnoy看到答案底部的一种dplyr解决方案-谢谢虽然我说没有数据表,但我只是喜欢它的优雅;我会把多余的空间用来comments@divibisan在发布我自己的解决方案之前,我没有看到过这样的评论,但它真的很好。我把它添加到我的帖子中。@divibisan在发布我自己的解决方案之前,我还没有看到这个评论,但它真的很不错。我把它添加到我的帖子里。