【问题标题】:Find the length of consecutive numbers in R查找R中连续数字的长度
【发布时间】:2020-11-13 17:09:43
【问题描述】:

我有一个如下所示的 data.frame:

data=data.frame(position=c(1,2,3,1,1,4,5,6,7,8,2,2),
             name=c("A","B","C","A","A","D","E","F","G","H","B","B"))

 position name
     1    A
     2    B
     3    C
     1    A
     1    A
     4    D
     5    E
     6    F
     7    G
     8    H
     2    B
     2    B

我希望能够在“位置”列中识别所有连续间隔 然后将每个间隔的长度粘贴到新列中。

我希望我的数据看起来像这样。

position  length
  1 - 3     3  
  4 - 8     5  

非常感谢任何帮助和评论

【问题讨论】:

    标签: r dataframe dplyr tidyverse


    【解决方案1】:

    这是一个基本的 R 解决方案。

    创建一个列sequence,它指示哪些行是连续的。

    data$sequence <- c(NA, head(data$position, -1)) + 1 == data$position
    data$sequence[[1]] <- data$sequence[[2]]
    
    data
    #>    position name sequence
    #> 1         1    A     TRUE
    #> 2         2    B     TRUE
    #> 3         3    C     TRUE
    #> 4         1    A    FALSE
    #> 5         1    A    FALSE
    #> 6         4    D    FALSE
    #> 7         5    E     TRUE
    #> 8         6    F     TRUE
    #> 9         7    G     TRUE
    #> 10        8    H     TRUE
    #> 11        2    B    FALSE
    #> 12        2    B    FALSE
    

    使用rle 构建运行长度。

    run_lengths <- rle(data$sequence)
    
    i_ends <- cumsum(run_lengths$lengths)[run_lengths$values]
    i_starts <- c(1, head(i_ends, -1))
    
    data.frame(
      position = paste0(data$position[i_starts], " - ", data$position[i_ends]),
      length = i_ends - i_starts
    )
    #>   position length
    #> 1    1 - 3      2
    #> 2    3 - 8      7
    

    【讨论】:

    • 谢谢你,保罗,你的时间。我想问你这部分代码中的“结束”是什么意思: i_starts
    • 我的代码中有错字。 ends 应该是 i_ends。我现在更新了代码。 i_ends 包含sequence == TRUE 所在的每个连续块的最后一行 ID。在本例中,它包含3, 10
    【解决方案2】:

    这行得通吗:

    library(dplyr)
    library(tidyr)
    library(data.table)
    data %>% mutate(ID = case_when (position == lead(position) - 1 ~ 1, TRUE ~ 0)) %>% 
    mutate(ID = case_when(position == lag(position) + 1 ~ 1, TRUE ~ ID)) %>% mutate(r = rleid(ID)) %>% filter(ID == 1) %>% 
    group_by(r) %>% mutate(position = paste(min(position),max(position), sep = '-'), length = length(unique(name))) %>% ungroup() %>% select(1,5) %>% distinct()
    # A tibble: 2 x 2
      position length
      <chr>     <int>
    1 1-3           3
    2 4-8           5
    > 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-08
      • 2013-05-19
      • 2023-01-20
      • 2014-05-30
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      相关资源
      最近更新 更多