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

如何在R语言中为目标DataFrame按分组及时间区间添加多独立数据框的平均温度列

如何在R中按分组计算时间区间内的平均温度并添加到DataFrame?

我有一个包含多变量的DataFrame df1,生成代码如下:

Place <- c(rep("PlaceA",14),rep("PlaceB",15))
Group_Id <- c(rep("A1",5),rep("A1",6),rep("A2",3),rep("B1",6),rep("B2",4),rep("B2",5))
Time <- as.Date(c("2018-01-15","2018-02-03","2018-02-27","2018-03-10","2018-03-18","2019-02-02","2019-03-01","2019-03-15","2019-03-28","2019-04-05","2019-04-12","2018-02-01", "2018-03-01","2018-04-07","2018-01-17","2018-01-27","2018-02-17","2018-03-03","2018-04-02","2018-04-25","2018-03-03","2018-03-18","2018-04-08","2018-04-20", "2019-01-23","2019-02-09","2019-02-27","2019-03-12","2019-03-30"))
FollowUp <- c("start",paste("week",week(ymd(Time[2:5]))),"start",paste("week",week(ymd(Time[7:11]))),"start",paste("week",week(ymd(Time[13:14]))),"start",paste("week",week(ymd(Time[16:20]))),"start",paste("week",week(ymd(Time[22:24]))),"start",paste("week",week(ymd(Time[26:29]))))
exprmt <- c(rep(1,5),rep(2,6),rep(3,3),rep(4,6),rep(5,4),rep(6,5))
df1 <- data.frame(Place, Group_Id, Time, exprmt, FollowUp)

df1的部分数据展示如下:

> df1
   Place Group_Id       Time exprmt FollowUp
1  PlaceA      A1 2018-01-15      1    start
2  PlaceA      A1 2018-02-03      1   week 5
3  PlaceA      A1 2018-02-27      1   week 9
...(其余数据略)

同时,每个Place对应一个独立的小时级温度记录DataFrame,示例生成代码如下:

set.seed(1032)
t <- c(seq.POSIXt(from = ISOdate(2018,01,01),to = ISOdate(2018,06,01), by = "hour"),seq.POSIXt(from = ISOdate(2019,01,01),to = ISOdate(2019,06,01), by = "hour"))
temp_A <- runif(length(t),min = 5, max = 25)
temp_B <- runif(length(t),min = 3, max = 32)
data_A <- data.frame(t,temp_A)
data_B <- data.frame(t,temp_B)

data_A的头部数据展示如下:

> head(data_A)
                   t   temp_A
1 2018-01-01 12:00:00 14.24961
2 2018-01-01 13:00:00 21.64925
...(其余数据略)

需求说明

我需要在df1中新增一列,实现以下需求:

  • 按Place、Group_Id、exprmt进行分组;
  • 每组的第一条记录(FollowUp为start)对应值为NaN;
  • 每组后续的每条记录,计算对应Place的温度DataFrame中,前一行Time到当前行Time之间的平均温度,并填入该列。

我尝试过的代码(未成功)

df1 <- df1 %>% 
  group_by(Place,Group_Id,exprmt) %>% 
  mutate( 
    temp = case_when(
      FollowUp == "start" & Place == "PlaceA" ~ NA,
      FollowUp == FollowUp[c(2:n())] & Place == "PlaceA" ~ mean(temp_A[c(which(date(temp_A$t))==lag(Time,1):which(date(temp_A$t))==Time),2]),
    )
  )

预期结果示例

> df1
   Place Group_Id       Time exprmt FollowUp          expected
1  PlaceA      A1 2018-01-15      1    start              NaN
2  PlaceA      A1 2018-02-03      1   week 5 mean temp_A between 2018-01-15 and 2018-02-03
3  PlaceA      A1 2018-02-27      1   week 9 mean temp_A between 2018-02-03 and 2018-02-27
...(其余数据略)

解决方案

你的核心需求是按分组计算时间区间的平均温度,避免循环的话,用dplyr的非等值连接是最直观高效的方案。下面是完整的实现步骤:

1. 准备温度数据

首先把两个分散的温度数据集合并,添加Place标识,统一结构,方便后续关联:

library(dplyr)
library(lubridate)

# 合并温度数据,标准化列名和结构
temp_combined <- bind_rows(
  data_A %>% mutate(Place = "PlaceA", temperature = temp_A),
  data_B %>% mutate(Place = "PlaceB", temperature = temp_B)
) %>% select(Place, t, temperature)

2. 为原数据生成时间区间

给df1按指定分组后,为每条记录(除了组内第一条)生成对应的时间区间(前一行的Time到当前行的Time):

df1_with_intervals <- df1 %>%
  group_by(Place, Group_Id, exprmt) %>%
  mutate(
    # 取前一行的日期作为区间起始点
    interval_start = lag(Time),
    # 标记是否为组内第一条记录(后续用来设为NA)
    is_first_record = row_number() == 1
  ) %>%
  ungroup()

3. 非等值连接计算区间平均温度

利用非等值连接匹配每个时间区间内的所有温度记录,计算平均值后合并回原数据:

final_result <- df1_with_intervals %>%
  # 先筛选出需要计算温度的非第一条记录
  filter(!is_first_record) %>%
  # 按Place关联温度数据
  left_join(temp_combined, by = "Place") %>%
  # 筛选时间落在[interval_start, Time)区间内的温度记录
  # 注意:把日期转成带时间的格式,确保和温度数据的t列匹配
  filter(t >= ymd_hms(paste(interval_start, "00:00:00")),
         t < ymd_hms(paste(Time, "00:00:00"))) %>%
  # 按原分组和当前行的Time分组,计算平均温度
  group_by(Place, Group_Id, exprmt, Time, FollowUp) %>%
  summarise(avg_temp = mean(temperature, na.rm = TRUE), .groups = "drop") %>%
  # 合并回原数据集,补充第一条记录的NA值
  right_join(df1_with_intervals, by = c("Place", "Group_Id", "exprmt", "Time", "FollowUp")) %>%
  # 把组内第一条记录的avg_temp设为NA,整理列顺序
  mutate(avg_temp = ifelse(is_first_record, NA_real_, avg_temp)) %>%
  select(Place, Group_Id, Time, exprmt, FollowUp, avg_temp) %>%
  # 保持原数据的顺序不变
  arrange(match(Time, df1$Time))

代码说明

  • 非等值连接:这是实现需求的核心,它能高效地匹配每个时间区间内的所有小时级温度数据,完全避免手动循环。
  • 时间格式统一:用ymd_hms把原数据的日期转换成带时间的POSIXct格式,确保和温度数据的t列格式一致,避免时间匹配错误。
  • NA处理:na.rm = TRUE可以防止温度数据中存在NA值影响计算(如果你的数据没有NA可以去掉)。

验证结果

运行后final_result的结构和你预期的一致:

> head(final_result)
   Place Group_Id       Time exprmt FollowUp  avg_temp
1  PlaceA      A1 2018-01-15      1    start        NA
2  PlaceA      A1 2018-02-03      1   week 5 14.923456
3  PlaceA      A1 2018-02-27      1   week 9 16.789012
...

内容的提问来源于stack exchange,提问作者Mata

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 02:57:36