【问题标题】:Getting multiple values per group based on two criteria根据两个标准为每组获取多个值
【发布时间】:2021-11-01 22:03:29
【问题描述】:

我正在尝试对数据集进行分组,并根据时间和速度的两个独立度量来获取第一个值和最高值。所以我需要每组最早记录的时间和速度,然后是每组最快记录的时间和速度。我已经走了这么远,但需要一些帮助......

library(tidyverse)
group <- c(1,1,1,1,1,2,2,3,3,4,4,4,4,4,4)
time <- c(1,6,4,5,7,12,10,2,3,8,9,11,13,14,15)
speed <- c(17,6, 99, 34, 12, 5, 67, 43, 23, 12, 15, 78, 61, 78, 20)
data = data.frame(group, time, speed)
summary = data %>% 
  group_by(group) %>%
  summarise(
    firstTime =  # lowest time
    HighestSpeedTime = , # time for highest speed
    firstSpeed = , #speed for lowest time
    highestSpeed = max(speed), # highest speed
  )

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    更新: 这应该可行:在第 4 组中,我们有 2 行平局:(我们在两个时间点有最高速度)!

    library(dplyr)
    data %>% 
      group_by(group) %>%
      summarise(
        firstTime = min(time), # lowest time
        HighestSpeedTime = time[which(speed==max(speed))], # time for highest speed
        firstSpeed = speed[which(time==min(time))],#speed for lowest time
        highestSpeed = max(speed) # highest speed
      ) 
    

    输出:

      group firstTime HighestSpeedTime firstSpeed highestSpeed
      <dbl>     <dbl>            <dbl>      <dbl>        <dbl>
    1     1         1                4         17           99
    2     2        10               10         67           67
    3     3         2                2         43           43
    4     4         8               11         12           78
    5     4         8               14         12           78
    

    【讨论】:

    • 感谢 TarJae,这是完美的。还要感谢 Zaw、Wimpel 和 Paul Smith 的意见。
    【解决方案2】:

    这行得通吗?

    library(tidyverse)
    group <- c(1,1,1,1,1,2,2,3,3,4,4,4,4,4,4)
    time <- c(1,6,4,5,7,12,10,2,3,8,9,11,13,14,15)
    speed <- c(17,6, 99, 34, 12, 5, 67, 43, 23, 12, 15, 78, 61, 78, 20)
    data = data.frame(group, time, speed)
    
    summary <-  data |> 
      arrange(group, time) |> 
      group_by(group) |> 
      summarise(
        firsttime = min(time),
        highest_speed = max(speed)
      ) |> 
      left_join(data, by = c("group", "highest_speed" = "speed")) |> 
      group_by(group) |> 
      slice(1) |> 
      rename(highest_speed_time = time) |> 
      left_join(data, by = c("group", "firsttime" = "time")) |> 
      rename(first_speed = speed)
    
    summary
    
      # group firsttime highest_speed highest_speed_time first_speed
      # <dbl>     <dbl>         <dbl>              <dbl>       <dbl>
      #     1         1            99                  4          17
      #     2        10            67                 10          67
      #     3         2            43                  2          43
      #     4         8            78                 11          12
    

    【讨论】:

      【解决方案3】:

      这是一个 data.table 方法

      library(data.table)
      setDT(data)
      temp <- data[data[, .I[speed == max(speed)], by = .(group)]$V1]
      setnames(temp, new = c("group", "maxSpeedTime", "maxSpeed"))
      # join together
      data[, .(firstTime  = time[1],
               firstSpeed = speed[1]), 
           by = .(group)][temp, on = .(group)]
      #    group firstTime firstSpeed maxSpeedTime maxSpeed
      # 1:     1         1         17            4       99
      # 2:     2        12          5           10       67
      # 3:     3         2         43            2       43
      # 4:     4         8         12           11       78
      # 5:     4         8         12           14       78
      

      【讨论】:

        【解决方案4】:

        另一种解决方案,使用链式inner_join

        library(tidyverse)
        
        data %>% 
          group_by(group) %>% 
          summarise(firstTime = min(time)) %>% 
          inner_join(data,by=c("group", "firstTime"="time")) %>% 
          rename(firstSpeed=speed) %>% 
          inner_join(
            data %>% 
              group_by(group) %>% 
              summarise(highestSpeed = max(speed)) %>% 
              inner_join(data,by=c("group", "highestSpeed"="speed")) 
          ) %>% 
          relocate(highestTime=time, .before="highestSpeed")
        
        #> Joining, by = "group"
        #> # A tibble: 5 × 5
        #>   group firstTime firstSpeed highestTime highestSpeed
        #>   <dbl>     <dbl>      <dbl>       <dbl>        <dbl>
        #> 1     1         1         17           4           99
        #> 2     2        10         67          10           67
        #> 3     3         2         43           2           43
        #> 4     4         8         12          11           78
        #> 5     4         8         12          14           78
        

        另一种解决方案,基于purrr::map_dfr

        library(tidyverse)
        
        data %>% 
          group_split(group) %>% 
          map_dfr(
            ~ data.frame(
              group = .x$group[1],
              firstTime = .x$time[min(.x$time) == .x$time],
              firstSpeed = .x$speed[min(.x$time) == .x$time],
              highestTime = .x$time[max(.x$speed) == .x$speed],
              highestSpeed = .x$speed[max(.x$speed) == .x$speed]))
        
        #>   group firstTime firstSpeed highestTime highestSpeed
        #> 1     1         1         17           4           99
        #> 2     2        10         67          10           67
        #> 3     3         2         43           2           43
        #> 4     4         8         12          11           78
        #> 5     4         8         12          14           78
        

        更简洁:

        library(tidyverse)
        
        data %>% 
          group_split(group) %>% 
          map_dfr(~ data.frame(
            group = integer(), firstTime = integer(), firstSpeed = integer(),
            highestTime = integer(), highestSpeed = integer()) %>% 
              add_row(!!!setNames(c(.x$group[1],.x[min(.x$time) == .x$time, -1],
                    .x[max(.x$speed) == .x$speed, -1]), names(.))))
        
        #>   group firstTime firstSpeed highestTime highestSpeed
        #> 1     1         1         17           4           99
        #> 2     2        10         67          10           67
        #> 3     3         2         43           2           43
        #> 4     4         8         12          11           78
        #> 5     4         8         12          14           78
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-02
          • 2022-10-23
          • 2015-11-20
          • 1970-01-01
          • 1970-01-01
          • 2017-05-29
          • 2021-03-25
          相关资源
          最近更新 更多