使用基于日期的聚合数据运行循环

Running loop with aggregated data based on dates

提问人:SPet 提问时间:12/29/2022 最后编辑:SPet 更新时间:12/30/2022 访问量:57

问:

我有一个大型的年度数据集,其中每小时都包含一个值。我对每日值或几天的值感兴趣。在我的脚本中,我指定了感兴趣的开始和结束日期,并根据单独的 R 脚本 (“run_seq 中每个小时的值聚合数据。R").

Date_From <- '2022-04-01'
Date_To <- '2022-04-02'
DF_hour<-(DfDHW %>%filter(as.Date(Hour) >= as.Date(Date_From) & as.Date(Hour) <= as.Date(Date_To)))
dummy<-as.numeric(DF_hour$Var*0+1)
dfdate <- aggregate(.~dummy, DFhour, sum)

这按预期工作。但是,我想在一个月的几天里循环重复这一点。我所做的是创建一个“日期从”和“日期到”的序列和一个数字序列号:

dates_from <- seq(as.Date("2022-04-01"), as.Date("2022-04-10"), by=1)
dates_to <- seq(as.Date("2022-04-02"), as.Date("2022-04-11"), by=1)
seq_num<-as.numeric(format(dates_from, format = "%d"))
df<-cbind.data.frame(dates_from, dates_to, seq_num)
dates_from dates_to seq_num
2022-04-01 2022-04-2 1
2022-04-02 2022-04-3 2

但是,如果我运行 for() 循环,代码将选择所有开始和结束日期,并汇总所有 10 天的数据。

for (x in seq_num) {
  source("run_seq.R") 
}

相反,我想选择与每个序列号 (1,2,3...) 相对应的开始和结束日期,以便在第一个循环中选择序列 nr 1 的开始/结束,并在第二个循环中选择序列 nr 的开始/结束。2等

例: 循环 1 = 序列 1:date_from = 2022-04-2;date_to = 2022-04-3; 循环 2 = 序列编号 2:date_from = 2022-04-3;date_to = 2022-04-4;

DfDHW 数据如下所示(总共 37 个变量,共 8760 行):

小时 变量1 变量2
2022-01-01 01:00:00 1.480 1.480
2022-01-01 02:00:00 0.957 0.957

dput(head(DfDHW) 产量:

structure(list(Hour = structure(c(1640995200, 1640998800, 1641002400, 
1641006000, 1641009600, 1641013200), class = c("POSIXct", "POSIXt"
), tzone = "Europe/Stockholm"), Var1 = c(1.48022736417965, 
0.957129616195086, 0.67616277119973, 0.516807667014335, 0.500124643187317, 
0.596748739907164), Var2 = c(1.48022736417965, 0.957129616195086, 
0.67616277119973, 0.516807667014335, 0.500124643187317, 0.596748739907164
), Var3 = c(1.48022736417965, 0.957129616195086, ...

我该如何实现?还是有更优雅的方式?

R 循环日期 序列

评论

0赞 Martin Gal 12/29/2022
你的剧本是什么样子的?我认为您需要将其放入以日期作为参数调用的函数中。这取决于脚本的实际结构。"run_seq.R"
0赞 SPet 12/29/2022
run_seq。R 脚本调用一系列脚本 - 第一个脚本包含 DF_hour<-(DfDHW %>%filter(as.日期(小时) >= 作为。日期(Date_From) & 作为。日期(小时) <= as.Date(Date_To))) 行,指定聚合日期。其余部分不相关,主要包含用于其他计算和链接到 GIS 图层的命令。
0赞 Andre Wildberg 12/29/2022
如果你能瞥一眼你的数据,那将有很大帮助,例如。dput(head(DfDHW))
0赞 SPet 12/29/2022
我添加了一个表和 dput(head(DfDHW))

答:

1赞 Andre Wildberg 12/30/2022 #1

筛选数据的方法

date_range <- seq(as.Date("2022-01-01"), as.Date("2022-01-04"), "day")

date_range <- data.frame(start = date_range[1:(length(date_range) - 1)], 
  end = date_range[2:length(date_range)])

date_range
       start        end
1 2022-01-01 2022-01-02
2 2022-01-02 2022-01-03
3 2022-01-03 2022-01-04

分别从“2022-01-01”到“2022-01-02”、“2022-01-02”到“2022-01-03”和“2022-01-03”到“2022-01-04”的天数。sum

setNames(
  data.frame(apply(date_range, 1, function(x) 
    colSums(DfDHW[DfDHW$Hour >= x["start"] & 
      DfDHW$Hour < x["end"], c("Var1", "Var2")]))), 
  apply(date_range, 1, paste, collapse="_to_"))
     2022-01-01_to_2022-01-02 2022-01-02_to_2022-01-03 2022-01-03_to_2022-01-04
Var1                 4.727201                        0                        0
Var2                 4.727201                        0                        0

数据

DfDHW <- structure(list(Hour = structure(c(1640995200, 1640998800, 1641002400, 
1641006000, 1641009600, 1641013200), class = c("POSIXct", "POSIXt"
), tzone = "Europe/Stockholm"), Var1 = c(1.48022736417965, 0.957129616195086, 
0.67616277119973, 0.516807667014335, 0.500124643187317, 0.596748739907164
), Var2 = c(1.48022736417965, 0.957129616195086, 0.67616277119973, 
0.516807667014335, 0.500124643187317, 0.596748739907164)), class = "data.frame", row.names = c(NA, 
-6L))
0赞 SPet 12/30/2022 #2

我听从了安德烈·维尔德伯格(Andre Wildberg)的建议,在循环之前进行了聚合。由于日期格式,建议的过滤对我不起作用。相反:

library(dplyr)
Df <- Df2%>% 
  group_by(date=as.Date(Hour)) %>%
  summarise(across(6:221, sum))

这会将所有每小时值汇总为每日值(总和)。 然后我设置日期:

Date_From <- '2022-04-01'
Date_To <- '2022-04-04' 

并在 while 循环中运行后台代码,此外还为每个循环保存一个绘图。

start <- Date_From
end <- Date_To
Datum <- start
while (Datum <= end)
{
  Date_Input=Datum
  source("run_seq.R") 
  print(g)
  ggplot2::ggsave(filename = paste0("plot_",Date_Input,".png"),g, path = "Plots", width = 2560, height = 1440, units = "px")
  Datum <- as.Date(Datum) + 1                  
}

这似乎有效。也许 for() 循环会更快,但这样我就可以选择任何日期。