如何从 POSIXct 变量创建 day/night 因子

How to create a day/night factor from POSIXct variable

我有一个包含 POSIXct date/times 列的数据 table。我想创建一个基于 POSIXct 时间戳指定 "day" 或 "night" 的列。日期在本地时间定义为 05:30:00 和 20:00:00 之间。

我尝试使用基于使用 strptime 创建的 "time of day" 列的 ifelse 语句创建新变量,但结果很奇怪。

这是一个简单的示例 - 将其设置为数据 table 以匹配我的真实数据集。

library(data.table)

SightingTime = c("2017-07-31 09:56:27 UTC", "2017-07-31 10:36:30 UTC", "2017-08-01 00:07:20 UTC","2017-08-01 01:31:00 UTC", "2017-08-01 10:38:23 UTC", "2017-08-01 21:13:06 UTC", "2017-08-02 15:13:30 UTC", "2017-08-02 18:05:28 UTC", "2017-08-02 21:04:08 UTC")
x=data.table(SightingTime)

首先,我从 date/time 变量中提取一天中的时间 - 我想要这个时间是当地时间,因为我将在当地时间指定 sunrise/sunset。

x$TOD = strftime(x$SightingTime, format="%H:%M:S",tz="America/Halifax")

我不确定为什么新的 TOD 变量仍然使用 UTC,即使我指定了不同的时区。

然后尝试使用 ifelse 语句创建一个新变量

x$daynight = with(x,
           ifelse(TOD > 05:30:00 & TOD < 20:00:00, "Day", "Night")) 

我很清楚这一点不正确,因为我收到警告消息并且 "day/night" 列中的结果没有意义。

我希望的是这样的。

             SightingTime      TOD daynight
1: 2017-07-31 09:56:27 UTC 06:56:27    Day
2: 2017-07-31 10:36:30 UTC 07:36:30    Day
3: 2017-08-01 00:07:20 UTC 21:07:20    Night
4: 2017-08-01 01:31:00 UTC 22:31:00    Night
5: 2017-08-01 10:38:23 UTC 07:38:23    Day
6: 2017-08-01 21:13:06 UTC 08:13:06    Day
7: 2017-08-02 15:13:30 UTC 12:13:30    Day
8: 2017-08-02 18:05:28 UTC 15:05:28    Day
9: 2017-08-02 21:04:08 UTC 18:04:08    Day

数据

library(data.table)

SightingTime_chr = c("2017-07-31 09:56:27 UTC", "2017-07-31 10:36:30 UTC", "2017-08-01 00:07:20 UTC","2017-08-01 01:31:00 UTC", "2017-08-01 10:38:23 UTC", "2017-08-01 21:13:06 UTC", "2017-08-02 15:13:30 UTC", "2017-08-02 18:05:28 UTC", "2017-08-02 21:04:08 UTC")
x = data.table(SightingTime_chr)

代码

您转换为日期时间(例如格式)时有几处不太正确:

x$SightingTime = as.POSIXct(x$SightingTime_chr, format = "%Y-%m-%d %H:%M:%S", tz = "UTC")
attributes(x$SightingTime)$tzone <- "America/Halifax"

我首先将字符串转换为 POSIXct,然后转换为 America/Halifax 时区,因为原始向量似乎是 UTC 日期时间(如果我错了,请省略第二步) .

x$TOD <- format(x$SightingTime, format="%H%M%S")

x$daynight = with(x, ifelse(TOD > "053000" & TOD < "200000", "Day", "Night")) 

我将一天中的时间转换为伪数值(这些值在技术上不正确,但这应该足以进行比较)。

x$daynight
[1] "Day"   "Day"   "Night" "Night" "Day"   "Day"   "Day"   "Day"   "Day" 

现在结果显示正确。

备选

我们可以得到一个优雅的解决方案,以防我们想要的不仅仅是 night/day:

nightday <- function(datetime) {
  paste(
    c("Night", "Morning", "Afternoon", "Evening", "Night")[
      cut(as.numeric(format(datetime, "%H%M")), c(0, 530, 1100, 1700 ,2000, 2359))
      ]
  )
}
nightday(x$SightingTime)
[1] "Morning"   "Morning"   "Night"     "Night"     "Morning"   "Evening"   "Afternoon" "Afternoon" "Evening"