【问题标题】:How to create a day/night factor from POSIXct variable如何从 POSIXct 变量创建昼夜因子
【发布时间】:2019-06-07 09:21:59
【问题描述】:

我有一个包含 POSIXct 日期/时间列的数据表。我想创建一个基于 POSIXct 时间戳指定“白天”或“夜晚”的列。当地时间定义为 05:30:00 到 20:00:00 之间的日期。

我尝试使用 ifelse 语句创建新变量,该语句基于使用 strptime 创建的“一天中的时间”列,但结果很奇怪。

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

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)

首先,我从日期/时间变量中提取一天中的时间 - 我想要在当地时间,因为我将在当地时间指定日出/日落。

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")) 

当我收到警告消息并且“日/夜”列中的结果没有意义时,我显然有一点不正确。

我希望是这样的。

             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

【问题讨论】:

  • 问题多于链接问题。从字符到 POSIXct 的转换不起作用,字符向量的 tz 似乎是 UTC 并且需要转换,一天中的时间没有正确提取,ifelse 中的比较不起作用,因为 05:30:00 是不是有效的格式(既不是数字也不是字符)。我写了一个比链接的答案更完整的答案,但现在无法发布。我认为这是错误地关闭...
  • @JBGruber 我的错误,我重新打开了。很抱歉给您带来不便。
  • 没问题。谢谢@Henrik
  • 鉴于你使用data.table,你也可以试试ITime类和betweenx[ , daynight := c("night", "day")[(as.ITime(SightingTime) %between% as.ITime(c("05:30:00", "20:00:00")) + 1)]]

标签: r time posixct


【解决方案1】:

数据

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,然后转换为美国/哈利法克斯时区,因为原始向量似乎是 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" 

现在结果看起来是正确的。

另类

this answer 我们可以得到一个优雅的解决方案,以防我们想要的不仅仅是夜晚/白天:

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"  

【讨论】:

  • 感谢您的支持 - 效果很好。我确实查看了您链接到的解决方案,但无法弄清楚如何将其应用于我的情况,因为我使用 5:30 作为截止时间而不是整个小时。
  • 我认为这应该没问题,因为您只是在寻找早/晚。但我添加了一个替代答案,因为我对@Henrik 链接的答案感兴趣。
  • 我真的很喜欢你的伪数字方法。我从来没有想过要那样做。这是一个很好的思考方式。谢谢。
  • 您将如何考虑日出和日落的变化?
猜你喜欢
  • 2020-10-10
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多