You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R语言中使用dplyr包实现分组最值对应日期匹配是否有更高效方法?

问题描述

我有如下格式的tibble数据框:

library(tidyverse)
date = seq(as.Date("2022/1/1"), by = "day", length.out = 16)
value = c(1.1,1.2,1.3,1.4,1.7,1.4,1.9,1.89,2,2.1,2.2,2.15,3,3.1,3.09,2.08)
variable = c(rep("a",4),rep("b",4),rep("c",4),rep("d",4))
df = tibble(date,value,variable);df

数据框结构如下:

# A tibble: 16 × 3
   date       value variable
   <date>     <dbl> <chr>   
 1 2022-01-01  1.1  a       
 2 2022-01-02  1.2  a       
 3 2022-01-03  1.3  a       
 4 2022-01-04  1.4  a       
 5 2022-01-05  1.7  b       
 6 2022-01-06  1.4  b       
 7 2022-01-07  1.9  b       
 8 2022-01-08  1.89 b       
 9 2022-01-09  2    c       
10 2022-01-10  2.1  c       
11 2022-01-11  2.2  c       
12 2022-01-12  2.15 c       
13 2022-01-13  3    d       
14 2022-01-14  3.1  d       
15 2022-01-15  3.09 d       
16 2022-01-16  2.08 d   

我的需求是按variable列分组,统计value列的最大值和最小值,并匹配这些统计值对应的date列。

我自己用tidyverse实现的代码如下:

df%>%group_by(variable)%>%
  summarise(MAX = max(value),MIN=min(value))%>%
  pivot_longer(!variable, names_to = "stats", values_to = "value")%>%
  left_join(.,df,by=c("value","variable"))

运行结果:

# A tibble: 8 × 4
  variable stats value date      
  <chr>    <chr> <dbl> <date>    
1 a        MAX    1.4  2022-01-04
2 a        MIN    1.1  2022-01-01
3 b        MAX    1.9  2022-01-07
4 b        MIN    1.4  2022-01-06
5 c        MAX    2.2  2022-01-11
6 c        MIN    2    2022-01-09
7 d        MAX    3.1  2022-01-14
8 d        MIN    2.08 2022-01-16

想请教有没有更高效的方法实现这种统计值与对应日期的匹配?


更高效的实现方法

你的方法需要经过summarise→pivot_longer→left_join三个步骤,其实可以通过直接在分组后提取最值对应的行来简化流程,避免额外的join操作,效率更高:

方法1:用slice_max+slice_min结合bind_rows

直接筛选出每组最大/最小值对应的行,再添加标记列区分类型,逻辑直观且省去中间转换步骤:

df %>%
  group_by(variable) %>%
  slice_max(value, n = 1) %>%
  mutate(stats = "MAX") %>%
  bind_rows(
    df %>%
      group_by(variable) %>%
      slice_min(value, n = 1) %>%
      mutate(stats = "MIN")
  ) %>%
  select(variable, stats, value, date) %>%
  arrange(variable, desc(stats))

方法2:在summarise中直接提取对应日期

利用which.max/which.min定位最值位置,直接提取对应日期,再通过pivot_longer整理格式:

df %>%
  group_by(variable) %>%
  summarise(
    max_value = max(value),
    max_date = date[which.max(value)],
    min_value = min(value),
    min_date = date[which.min(value)]
  ) %>%
  pivot_longer(
    cols = -variable,
    names_to = c(".value", "stats"),
    names_sep = "_"
  ) %>%
  select(variable, stats, value, date)

这个方法只需要一次分组聚合,通过names_sep参数直接拆分列名,代码更紧凑。

方法3:用data.table处理大数据集

如果是超大数据集,data.table的性能优势更明显,写法也更简洁:

library(data.table)
setDT(df)

df[, .(
  stats = c("MAX", "MIN"),
  value = c(max(value), min(value)),
  date = c(date[which.max(value)], date[which.min(value)])
), by = variable]

内容的提问来源于stack exchange,提问作者Homer Jay Simpson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 19:30:43