【问题标题】:How to extract minimum and maximum values based on conditions in R如何根据R中的条件提取最小值和最大值
【发布时间】:2022-01-05 09:31:18
【问题描述】:

我有一个包含数千行的数据框,我需要输出属于同一组和类的数据部分的最小值和最大值。我需要的是读取第一个起始值,将其与结束列中的前一个值进行比较,如果较小,则跳转到下一行,依此类推,直到起始值大于前一个结束值,然后输出最小起始值该部分的值和最大值。我的数据已经按 group-class-start-end 排序。

df <- data.frame(group = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"),
  class = c("2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3"),
  start = c("23477018","23535465","23567386","24708741","24708741","24708741","48339885","87274","87274","127819","1832772","1832772","1832772","6733569","7005524","7005524","7644572","8095433","8095433","8095433"),
  end = c("47341413", "47341413", "47909872","42247834","47776347","47909872","53818713","3161655","3479466","3503792","3503792","4916249","5329014","8089225","12037894","13934484","12037894","12037894","13626119","13934484"))

我想要实现的输出是:

  group     class   start     end     
1   1       2    23477018   47909872
2   1       2    48339885   53818713
3   1       3    87274      5329014
4   1       3    6733569    13934484

非常感谢任何关于如何实现这一目标的想法。

【问题讨论】:

    标签: r loops max minimum multiple-conditions


    【解决方案1】:

    我为此使用了 data.table。
    我的方法是首先将开始和结束更改为整数,否则会出现排序问题。
    找出哪些行满足 start > max(所有先前的结束),然后使用 cumsum 给出一个递增的子组数。
    然后它只是按子组的简单最小值和最大值。
    没有循环可以使这个过程尽可能快。

    library(data.table)
    df <- data.frame(group = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"),
                     class = c("2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3"),
                     start = c("23477018","23535465","23567386","24708741","24708741","24708741","48339885","87274","87274","127819","1832772","1832772","1832772","6733569","7005524","7005524","7644572","8095433","8095433","8095433"),
                     end = c("47341413", "47341413", "47909872","42247834","47776347","47909872","53818713","3161655","3479466","3503792","3503792","4916249","5329014","8089225","12037894","13934484","12037894","12037894","13626119","13934484"))
    
    setDT(df)
    df[, c('start', 'end') := lapply(.SD, as.integer), .SDcols = c('start', 'end')]
    df[, subgrp := cumsum(start > shift(cummax(.SD$end), fill = 0)), keyby = c('group', 'class')]
    ans <- df[, .(start = min(start), end = max(end)), keyby = c('group', 'class', 'subgrp')]
    ans[, subgrp := NULL][]
    
       group class    start      end
    1:     1     2 23477018 47909872
    2:     1     2 48339885 53818713
    3:     1     3    87274  5329014
    4:     1     3  6733569 13934484
    

    【讨论】:

    • 非常感谢布赖恩·蒙哥马利!我只想考虑分组、开始和结束,但不考虑类,我认为我可以从 key by 中删除“类”是否正确?
    • 是的。没错。
    【解决方案2】:

    这是一个 tidyverse 解决方案:

    library(tidyverse)
                
    df <- data.frame(
      group = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"),
      class = c("2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3"),
      start = c("23477018","23535465","23567386","24708741","24708741","24708741","48339885","87274","87274","127819","1832772","1832772","1832772","6733569","7005524","7005524","7644572","8095433","8095433","8095433"),
      end = c("47341413", "47341413", "47909872","42247834","47776347","47909872","53818713","3161655","3479466","3503792","3503792","4916249","5329014","8089225","12037894","13934484","12037894","12037894","13626119","13934484"))
    df %>% 
      group_by(group, class) %>% 
      mutate(
        start = as.integer(start),
        end = as.integer(end),
        end_lag = lag(end),
        larger_flag = case_when(start > end_lag & !is.na(end_lag) ~ 1, TRUE ~ 0),
        sub_group = cumsum(larger_flag)) %>% 
      group_by(group, class, sub_group) %>% 
      summarise(
        start = min(start),
        end = max(end),
        .groups = 'drop'
        ) %>% 
      select(-sub_group)
     # A tibble: 4 x 4
       group class    start      max
       <chr> <chr>    <int>    <int>
     1 1     2     23477018 47909872
     2 1     2     48339885 53818713
     3 1     3        87274  5329014
     4 1     3      6733569 13934484
    

    【讨论】:

      猜你喜欢
      • 2012-09-30
      • 2021-06-05
      • 1970-01-01
      • 2017-08-17
      • 2016-07-13
      • 1970-01-01
      • 1970-01-01
      • 2022-06-28
      • 1970-01-01
      相关资源
      最近更新 更多