代码之家  ›  专栏  ›  技术社区  ›  tjebo

在包含第一个不同值之前获取观察结果(允许使用“无开关”的组)

  •  1
  • tjebo  · 技术社区  · 6 年前

    我有一个稍微复杂的方法,从第一行(总是以相同的值开始)到(包括)第一个不同的值,一组一组地分割一个数据帧。

    我想用 slice(1:min(which == new.value)) ,但有些群体并没有发生这种转变——这就是让我头痛的原因。我可以把数据分成有开关的组,而不是有开关的组,只对有开关的组进行计算,但我想知道是否有更优雅的选择。我愿意接受任何包裹。

    library(dplyr)
    
    mydf <- data.frame(group = rep(letters[1:3], each = 4), value = c(1,2,2,2, 1, 1,1,1,1,1,2,2))
    

    以下命令不起作用,因为有些组没有“switch”

    mydf %>% group_by(group) %>% slice(1: min(which(value == 2)))
    #> Warning in min(which(value == 2)): no non-missing arguments to min; returning
    #> Inf
    #> Error in 1:min(which(value == 2)): result would be too long a vector
    

    仅对具有开关并与“无开关”绑定的组执行切片操作:

    mydf_grouped <- mydf %>% group_by(group) 
    
    mydf_grouped %>% 
      filter(any(value == 2)) %>% 
      slice(1: min(which(value == 2))) %>% 
      bind_rows(filter(mydf_grouped, !any(value ==2)))
    #> # A tibble: 9 x 2
    #> # Groups:   group [3]
    #>   group value
    #>   <fct> <dbl>
    #> 1 a         1
    #> 2 a         2
    #> 3 c         1
    #> 4 c         1
    #> 5 c         2
    #> 6 b         1
    #> 7 b         1
    #> 8 b         1
    #> 9 b         1
    

    于2019年12月22日由 reprex package (第0.3.0版)

    2 回复  |  直到 6 年前
        1
  •  2
  •   G. Grothendieck    6 年前

    我们希望所有值为1的行以及每个组中前2的行:

    mydf %>%
      group_by(group)  %>%
      filter(value == 1 | cumsum(value == 2) == 1) %>%
      ungroup
    
        2
  •  2
  •   akrun    6 年前

    在这里,一个选择是通过 if/else 条件

    library(dplyr)
    mydf %>% 
        group_by(group) %>%
        slice(if(!2  %in% value) row_number() else seq_len(match(2, value)) )
    

    或者更紧凑些,改变 nomatch 在里面 match n()

    mydf %>% 
       group_by(group) %>%
       slice(seq_len(match(2, value, nomatch = n())))
    # A tibble: 9 x 2
    # Groups:   group [3]
    #  group value
    #  <fct> <dbl>
    #1 a         1
    #2 a         2
    #3 b         1
    #4 b         1
    #5 b         1
    #6 b         1
    #7 c         1
    #8 c         1
    #9 c         2