根据数据框列的参数使用dplyr :: mutate和lubridate :: force_tz

时间:2016-04-13 12:18:03

标签: r timezone dplyr lubridate

我正在尝试使用lubridate :: force_tz将时区信息添加到格式化为字符串的时间戳(日期+时间)(as.character())。两者都存储在数据框中的两列:

require(lubridate)
require(dplyr)
row1<-c(as.character(now()),"Etc/UTC")
row2<-c(as.character(now()+5),"America/Chicago")
df<-as.data.frame(rbind(row1,row2))
names(df)<-c("dt","tz")

x<-force_tz(as.POSIXct(as.character(now())),"Etc/UTC") #works
df<-df%>%mutate(newDT=force_tz(as.POSIXct(dt),tz)) #fails

我得到:UseMethod(“mutate_”)中的错误:   没有适用于“mutate_”的方法应用于类“c”('matrix','character')的对象“

根据Stibu的评论,我尝试了(一种类似非R的方法)迭代:

for (i in seq(from=1,to=length(df$dt))){
timestamp<-as.character(df[i,1])
tz<-as.character(df[i,2])
print(tz)
newdt<-force_tz(as.POSIXct(timestamp),tz)
df[i,3]<-newdt
print(attr(df[i,3],"tzone"))
df$timezone<-attr(df[i,3],"tzone")
}

这正确地提取了值,但似乎很难将tz的值设置为遇到的第一个值 - 奇怪的是:

[1] "Etc/UTC"
[1] "Etc/UTC"
[1] "America/Chicago"
[1] "Etc/UTC"

我原本预计最后一次打印会产生"America/Chicago" 然后df看起来像:

 > df
               dt              tz               newDT timezone
 1 2016-04-13 23:07:45         Etc/UTC 2016-04-13 23:07:45  Etc/UTC
 2 2016-04-13 23:07:50 America/Chicago 2016-04-14 04:07:50  Etc/UTC

1 个答案:

答案 0 :(得分:1)

您的代码实际上有两个问题,我将在下面单独讨论。

dplyr适用于数据框

您的df是一个矩阵,而不是数据框。但是mutate()(和dplyr中的函数一般)适用于数据帧。该错误消息只是告诉您mutate()不知道如何处理矩阵。

您可以通过将df转换为数据框来解决此问题:

df <- as.data.frame(df)
names(df)<-c("dt","tz")

关于names()的注释:此函数可用于获取/设置数据框的列名。对于矩阵,相应的函数是colnames()。您在矩阵上使用names()设置矩阵的列名称。因此,转换后也不会设置数据框的名称。

您还可以从头开始创建数据框,如下所示:

df <- data.frame(dt = as.character(c(now(), now() + 5)),
                 tz = c("Etc/UTC", "America/Chicago"),
                 stringsAsFactors = FALSE)

请注意,您需要按照列方式定义内容,而不是像行那样按行定义。

如果您使用数据框df,则mutate()不会出现错误。

每个载体一个时区

不幸的是,还有第二个问题。你想做什么根本无法做到。原因如下。

让我们将df的第一列转换为时区POSIXct CET

ts <- as.POSIXct(df$dt, tz = "CET")
ts
## [1] "2016-04-13 14:42:26 CEST" "2016-04-13 14:42:31 CEST"

让我们尝试对两个时区做同样的事情:

ts <- as.POSIXct(df$dt, tz = c("CET", "UTC"))
## Error in strptime(xx, f <- "%Y-%m-%d %H:%M:%OS", tz = tz) : 
##   invalid 'tz' value

这不起作用。原因是每个矢量单个时区而不是矢量中每个元素的时区。查看ts

的属性
attributes(ts)
## $class
## [1] "POSIXct" "POSIXt" 
## 
## $tzone
## [1] "CET"

时区被设置为整个向量的属性,并且它不是每个元素的属性。