首页 > 解决方案 > 将一天中的阶段分配给每个日期 - 但速度很快

问题描述

我想将列表中的元素与数据框中的间隔进行比较,并将相应的间隔分配给该元素。

就我而言,我想获得一天中的一个阶段(即早上、白天、晚上、晚上)进行测量。我找到了 R 包“suncalc”,它为这些阶段创建了间隔,并且还有一个解决方案来分配一天中的这些阶段。但是这很慢,我想知道如何更快地做到这一点。

#make a list of different days and times
times<-seq.POSIXt(from=Sys.time(),
                 to=Sys.time()+2*24*60*60,length.out = 50)

#load the suncalc package
library(suncalc)

#a function to get a phase for one point in time
get.dayphase<-function(x){
  phases<-getSunlightTimes(date=as.Date(x,tz=Sys.timezone()),
                           lat=52.52,lon=13.40,
                           tz=Sys.timezone())
  if(x<phases$nightEnd)return("night_morning")
  if(x>=phases$nightEnd&x<phases$goldenHourEnd)return("morning")
  if(x>=phases$goldenHourEnd&x<phases$goldenHour)return("day")
  if(x>=phases$goldenHour&x<phases$night)return("evening")
  if(x>=phases$night)return("night_evening")
}

#use sapply to get a phase for each point in time of the list
df=data.frame(time=times,dayphase=sapply(times,get.dayphase))

理想但缓慢的结果:

head(df)
                 time dayphase

1 2019-09-05 16:12:08      day
2 2019-09-05 17:10:55      day
3 2019-09-05 18:09:41      day
4 2019-09-05 19:08:28  evening
5 2019-09-05 20:07:14  evening
6 2019-09-05 21:06:01  evening

基本上,这就是我想要的。但是当我在很多时间点上运行它时它太慢了。getSunlightTimes()也可以获取日期列表并返回数据表,但我不知道如何处理以获得所需的结果。谢谢你的帮助

标签: rdatetime

解决方案


使您的流程变慢的很可能是sapply函数,它基本上是一个隐藏for循环。

为了提高性能,您需要对代码进行矢量化。可以采用getSunlightTimes日期向量。此外,dplyr 包中的函数不是使用一系列if语句,而是case_when简化了代码,并且应该减少逻辑操作的数量。

library(dplyr)

times<-seq.POSIXt(from=Sys.time(),
                  to=Sys.time()+2*24*60*60,length.out = 50)

library(suncalc)
#a function to get phases for all of the times
phases<-getSunlightTimes(as.Date(times),
                     lat=52.52,lon=13.40,
                     tz=Sys.timezone(),
                     keep = c("nightEnd", "goldenHourEnd", "goldenHour", "night"))

dayphase<-case_when(
  times < phases$nightEnd ~ "night_morning",
  times < phases$goldenHourEnd ~ "morning",
  times < phases$goldenHour ~ "day",
  times < phases$night ~ "evening",
  TRUE ~ "night_evening"
)

这应该提供显着的改进。如果您每天有大量时间,则可以进一步提高性能。如果是这种情况,请每天计算一次阶段数据帧,然后将此结果用作各个时间的查找表。


推荐阅读