【问题标题】:Vectorised time zone conversion with lubridate使用 lubridate 进行矢量化时区转换
【发布时间】:2018-06-25 19:01:01
【问题描述】:

我有一个包含一列日期时间字符串的数据框:

library(tidyverse)
library(lubridate)

testdf = data_frame(
  mytz = c('Australia/Sydney', 'Australia/Adelaide', 'Australia/Perth'),
  mydt = c('2018-01-17T09:15:00', '2018-01-17T09:16:00', '2018-01-17T09:18:00'))

testdf

#  A tibble: 3 x 2
#   mytz               mydt
#   <chr>              <chr>
# 1 Australia/Sydney   2018-01-17T09:15:00
# 2 Australia/Adelaide 2018-01-17T09:16:00
# 3 Australia/Perth    2018-01-17T09:18:00

我想将这些日期时间字符串转换为具有各自时区的 POSIX 日期时间对象:

testdf %>% mutate(mydt_new = ymd_hms(mydt, tz = mytz))

mutate_impl(.data, dots) 中的错误: 评估错误:tz 参数必须是单个字符串。 另外:警告信息: 在 if (tz != "UTC") { : 条件的长度 > 1,并且只使用第一个元素

如果我使用不带时区的ymd_hms 并将其通过管道传输到force_tz,我会得到相同的结果。是否可以得出结论,当涉及到时区操作时,lubridate 不支持任何类型的矢量化?

【问题讨论】:

  • 也许是testdf %&gt;% rowwise %&gt;% mutate(mydt_new = ymd_hms(mydt, tz = mytz)) ?
  • 行得通!我不明白为什么需要rowwise,但...
  • 我想如果它在组上运行,并且每个组有一行,那么 tz 在每次调用中的长度仅为 1。即使我有多行具有相同的时区,那也可以。谢谢!
  • 如果您愿意,很高兴将此作为已接受的答案!
  • 好的。让我来处理。

标签: r date datetime tidyverse lubridate


【解决方案1】:

另一个选项是map2。将不同的tz 输出存储在list 中可能会更好,因为这可能会被强制转换为单个tz

library(tidyverse)
out <- testdf %>%
         mutate(mydt_new = map2(mydt, mytz, ~ymd_hms(.x, tz = .y)))

如果需要,可以unnested

out %>%
   unnest

list 中的值是

out %>%
   pull(mydt_new)
#[[1]]
#[1] "2018-01-17 09:15:00 AEDT"

#[[2]]
#[1] "2018-01-17 09:16:00 ACDT"

#[[3]]
#[1] "2018-01-17 09:18:00 AWST"

【讨论】:

  • @rensa 更好,因为该列仅允许单个时区,并且强制到单个时区可能会有所不同。
  • @rensa 有趣的是,如果我使用unnest,与 jazzuro 的值相比,我得到的值不同。因此,它将强制转换为不同的tz
  • 如果可以的话,我会接受你的两个答案? 但我认为,作为一般情况,优先考虑输出的可预测性是个好主意。
  • @akrun 感谢您的回复。我很高兴听到你也会这样做。我会坚持这种方法。顺便说一句,你仍然在这里摇摆不定。这很酷。我还有很多东西要向你学习。
  • @akrun 我认为你是我声誉的主要贡献者。非常感激。 :)
【解决方案2】:

tz argument must be a single character string. 表示ymd_hms() 中有多个时区。为了确保函数中只有一个时区,我使用了rowwise()。请注意,我不在澳大利亚时区。所以我不确定我得到的结果是否和你的一样。

testdf <- data_frame(mytz = c('Australia/Sydney', 'Australia/Adelaide', 'Australia/Perth'),
                     mydt = c('2018-01-17 09:15:00', '2018-01-17 09:16:00', '2018-01-17 09:18:00'))

testdf %>% 
rowwise %>% 
mutate(mydt_new = ymd_hms(mydt, tz = mytz))

  mytz               mydt                mydt_new           
  <chr>              <chr>               <dttm>             
1 Australia/Sydney   2018-01-17 09:15:00 2018-01-17 06:15:00
2 Australia/Adelaide 2018-01-17 09:16:00 2018-01-17 06:46:00
3 Australia/Perth    2018-01-17 09:18:00 2018-01-17 09:18:00

【讨论】:

  • 是的,我得到了相同的输出。似乎 tibble 打印方法从列中的时区中选择时区,而不是用户的本地时区。
  • @rensa 我明白了。这是一件好事。感谢您的信息。 :)
  • @jazzurro 我发布了一个解决方案,因为它是关于时区如何强制的有趣比较。希望你不要介意。
  • @akrun 我意识到您是在要求检查已删除评论中的代码。那一刻我只是无法回复你。对不起。我想你调查了一个有趣的案例。在这一点上我还有一些问题要问,但我现在不能在这里承诺。我可以稍后在这里联系您吗?
  • @akrun 如果我按照你的想法做了以下事情。 testdf %&gt;% rowwise %&gt;% mutate(mydt_new = format(ymd_hms(mydt, tz = mytz), usetz = TRUE)).
猜你喜欢
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
  • 2010-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多