我正在尝试使用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
答案 0 :(得分:1)
您的代码实际上有两个问题,我将在下面单独讨论。
您的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"
时区被设置为整个向量的属性,并且它不是每个元素的属性。