【问题标题】:Using `rle` function along with `dplyr` `group_by` command to mapping grouping variable使用 `rle` 函数和 `dplyr` `group_by` 命令映射分组变量
【发布时间】:2020-05-24 19:06:30
【问题描述】:

我有一个包含三列的数据框,其信息类似于下面给出的数据框。现在我希望根据a 列中的信息提取信息搜索模式。

基于少数开发人员(@thelatemail 和@David T)的支持,我能够使用rle 函数识别模式,请参阅此处-using rle function to identify pattern。现在,我希望继续并将分组信息添加到提取的模式中。我尝试使用 dplyr do 函数 - 请参阅下面的代码。但是,这不起作用。

还提供了示例数据和所需的输出以供您参考。

##mycode that produces error - needs to be fixed
test <- data%>%
  group_by(b, c)%>%
  do(.,  data.frame(from = rle(.$a)$values), to = lead(rle(.$a)$values))
##code to create the data frame
a <- c( "a", "b", "b", "b", "a", "c", "a", "b", "d", "d", "d", "e", "f", "f", "e", "e")
b <- c(rep("experiment", times = 8), rep("control", times = 8))
c <- c(rep("A01", times = 4), rep("A02", times = 4), rep("A03", times = 4), rep("A04", times = 4))
data <- data.frame(c,b,a)

## desired output

    c      b         from  to    fromCount toCount
                    <chr> <chr>     <int>   <int>
 1 A01 experimental  a     b             1       3
 2 A02 experimental  a     c             1       1
 3 A02 experimental  c     a             1       1
 4 A02 experimental  a     b             1       1
 5 A03 control       d     e             3       1
 6 A04 control       f     e             2       2

与之前的帖子here 相比,由于我们将分组应用于a 列,因此信息被压缩了。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我们可以使用来自data.tablerleid

    library(data.table)
    library(dplyr)
    data %>% 
      group_by(b, c, grp = rleid(a)) %>%
      summarise(from = first(a), fromCount = n()) %>% 
      mutate(to = lead(from), toCount = lead(fromCount)) %>%
      ungroup %>%
      select(-grp) %>% 
      filter(!is.na(to)) %>%
      arrange(c)
    # A tibble: 6 x 6
    #  b          c     from  fromCount to    toCount
    #  <chr>      <chr> <chr>     <int> <chr>   <int>
    #1 experiment A01   a             1 b           3
    #2 experiment A02   a             1 c           1
    #3 experiment A02   c             1 a           1
    #4 experiment A02   a             1 b           1
    #5 control    A03   d             3 e           1
    #6 control    A04   f             2 e           2
    

    或使用rle,在按'b'、'c'、summariserle 分组后创建list 列,然后从@987654328 中的列中提取'值'和'长度' @,在'from'的lead上创建'to','toCount','fromCount'列filterNA元素和arrange基于'c'列的行

    data %>% 
        group_by(b, c) %>%
        summarise(rl = list(rle(a)), 
                  from = rl[[1]]$values, 
                  fromCount = rl[[1]]$lengths) %>% 
        mutate(to = lead(from), 
               toCount = lead(fromCount)) %>%
        ungroup %>% 
        select(-rl) %>% 
        filter(!is.na(to)) %>% 
        arrange(c)
    # A tibble: 6 x 6
    #  b          c     from  fromCount to    toCount
    #  <chr>      <chr> <chr>     <int> <chr>   <int>
    #1 experiment A01   a             1 b           3
    #2 experiment A02   a             1 c           1
    #3 experiment A02   c             1 a           1
    #4 experiment A02   a             1 b           1
    #5 control    A03   d             3 e           1
    #6 control    A04   f             2 e           2
    

    我们还可以使用map 循环遍历rle list 列('rl'),提取组件,然后在lengths 中获取leadvalues 中的tibble ,使用unnest_wider 创建列和unnest list 结构,filter 出NA 元素和arrange

    library(tidyr)
    library(purrr)
    data %>% 
         group_by(b, c) %>%
         summarise(rl = list(rle(a))) %>%
         ungroup %>%
         mutate(out = map(rl, 
              ~ tibble(from = .x$values,
                       fromCount = .x$lengths,
                       to = lead(from), 
                       toCount = lead(fromCount)))) %>%
         unnest_wider(c(out)) %>% 
         unnest(from:toCount) %>%
         filter(!is.na(to)) %>% 
         arrange(c) %>% 
         select(-rl)
    

    【讨论】:

    • 第一个解决方案适用于提供的示例。而使用rle 函数的第二个解决方案会引发错误 - 错误:from 列的长度必须为 1(汇总值),而不是 2。它在你的最后工作吗??
    • @BalachandarKaliappan 是的,它对我来说很好用。你能显示你的 dplyr 包版本吗
    • 我使用的是开发版的dplyr
    • @BalachandarKaliappan 我用修改后的解决方案进行了更新。我希望它对你有用
    • @BalachandarKaliappan 谢谢,我理解为什么我的解决方案不起作用,我认为这可能是开发中的一个错误,因为summarise 应该只返回一行作为输出,但是当我们使用$values$lengths 进行提取,它只是扩展行而不是抛出错误
    【解决方案2】:

    或者在tidyverse 中,创建一个函数来执行rle 以跟踪单个主题

    rleSlice <- function(Tracking) {
    
      rlTrack <- rle(as.character(Tracking))  # Strip the levels from the factor, they interfere
      tibble(from = rlTrack$values, to = lead(rlTrack$values),
                     fromCount = rlTrack$lengths, toCount = lead(rlTrack$lengths)) %>% 
        filter(!is.na(to)) %>% 
        list()
    }
    

    确保它正常运行

    [[1]]
    rleSlice(c("a", "b", "b", "b", "c"))
    
    A tibble: 2 x 4
      from  to    fromCount toCount
      <chr> <chr>     <int>   <int>
    1 a     b             1       3
    2 b     c             3       1
    

    现在我们将分组并为每个参与者获取 rle

    data %>% 
      as_tibble() %>% 
        # This is easier to track than all these a,b,c's
      rename(Subject = c, Test = b, Tracking = a) %>% 
      group_by(Subject, Test) %>% 
      summarise(Slice = rleSlice(Tracking)) %>% 
      unnest(col = "Slice") %>% 
      ungroup()
    
    # A tibble: 6 x 6
      Subject Test       from  to    fromCount toCount
      <fct>   <fct>      <chr> <chr>     <int>   <int>
    1 A01     experiment a     b             1       3
    2 A02     experiment a     c             1       1
    3 A02     experiment c     a             1       1
    4 A02     experiment a     b             1       1
    5 A03     control    d     e             3       1
    6 A04     control    f     e             2       2
    

    【讨论】:

    • 感谢@David T - 这个解决方案也很有效。感谢您为解决我的问题所做的努力。
    猜你喜欢
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 2014-06-04
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    相关资源
    最近更新 更多