这是我的第一个stackoverflow问题,所以请提前为礼节或演示中的任何失误道歉。
我正在使用R中的dygraphs()包(运行Mavericks的Mac上的3.3.3,使用RStudio)来绘制18世纪剧院的票房收据的时间序列。日期为1789-04-14至1791-03-07。我使用的是最新版本的xts软件包(0.10-0),但问题在之前的版本中是相同的。作为xts对象,数据如下所示:
head(receipts.xts)
kr
1789-04-14 15454
1789-04-20 6985
1789-04-22 4545
1789-04-24 5342
1789-04-26 5791
1789-04-28 25139
为索引导入的日期属于date
类型。
(' kr'代表' kreuzer,'当时货币单位的细分。)
创建dygraph的代码是:
dygraph(receipts.xts,
main = "Opera Receipts, Burgtheater, 1789-1791") %>%
dySeries("kr", label = "Receipts (kr)") %>%
dyLegend(show="always", hideOnMouseOut =FALSE) %>% dyRangeSelector()
图例中的所有日期都比xts对象中的相应日期提前一天显示。这在附带的屏幕截图中显示,其中第一个数据点是1789-04-14,但在图例中的RStudio查看器中显示为" Apr,13,1789" (在月份缩写之后,我无法找到摆脱不需要的逗号的方法。)
奇怪的是,当我将此图表保存为html时,网页上的图例会显示正确的日期!
我尝试了各种各样的解决方案,但到目前为止还没有任何效果。这看起来像一个bug,但是我不清楚bug在哪里(在dtgraphs包中?在RStudio中?在xts中?)。我的问题似乎与此类似:
Date bug in dygraph in dygraphs package (using JavaScript) in R
但这个问题似乎从来没有得到明确的答案。我可以在RStudio查看器的图例中显示正确日期的唯一方法是将一天添加到用作xts对象索引的所有日期(使用lubridate),但是日期不正确HTML
****编辑于7/10/17回应Dirk的回复****
我已经意识到隐藏"隐藏"时区问题与日期有关,并尝试了其他一些方法来解决这个问题,尽管还没有像Dirk建议的那样用Sys.setenv()
设置时区。我只是试过了,它也没有解决问题。我这次的步骤是:
operas$Date <- as.character(operas$Date)
Sys.setenv(tz="UTC")
receipts.xts <- xts(operas$Receipts, as.Date(operas$Date))
colnames(receipts.xts) <- "kr"
(在原始数据框中,日期已经是date
类型,但我想从头开始显示此问题。)dygraphs
代码与我原始示例中的代码相同。
结果完全相同:在 RStudio viewer 中检查时,图例中的日期过早,但在浏览器中查看时导出的html中的日期是正确的。
所以看起来这个问题可能就在其他地方。
在我的原始示例中使用lubridate
as_date()
只反映了我最近尝试修复的一个问题。我的原始代码使用了as.Date()。但是感谢指针。
****一些样本数据****
> dput(receipts.test)
structure(list(Date = c("1789-04-14", "1789-04-20", "1789-04-22",
"1789-04-24", "1789-04-26", "1789-04-28", "1789-04-30", "1789-05-02",
"1789-05-04", "1789-05-06"), Receipts = c(15454L, 6985L, 4545L,
5342L, 5791L, 25139L, 6897L, 4268L, 2400L, 4515L)), .Names = c("Date",
"Receipts"), row.names = c(NA, 10L), class = c("tbl_df", "tbl",
"data.frame"))
答案 0 :(得分:1)
所以让我们做一些教程。从日期开始,转换为POSIXct然后格式化:
R> format(as.POSIXct(as.Date("2017-07-08")))
[1] "2017-07-07 19:00:00"
R>
看看会发生什么?我在芝加哥,从午夜减去的五个小时是我对UTC的偏移。一种可能的解决方法是将时区设置为UTC:
R> Sys.setenv(TZ="UTC")
R> format(as.POSIXct(as.Date("2017-07-08")))
[1] "2017-07-08"
R>
现在相同的输入数据被正确地“打印”为相同的日期。
课程:警惕Date
到POSIXct
次转化。这里你需要的只是适当的时区(对于格式化的上下文)。
最后,您确实不需要使用lubridate包来调整日期。 R本身做得很好:
R> as.Date("2017-07-08")
[1] "2017-07-08"
R> as.Date("2017-07-08") + 1:3
[1] "2017-07-09" "2017-07-10" "2017-07-11"
R>
日期和时间对程序员和用户来说都是一项挑战。 R有很好的支持。花点时间学习它,一次一个问题。
编辑:好的,在我再次被拖入此处之后,这里有代码和图表。
d <- structure(list(Date = c("1789-04-14", "1789-04-20", "1789-04-22",
"1789-04-24", "1789-04-26", "1789-04-28",
"1789-04-30", "1789-05-02",
"1789-05-04", "1789-05-06"),
Receipts = c(15454L, 6985L, 4545L, 5342L, 5791L, 25139L,
6897L, 4268L, 2400L, 4515L)),
.Names = c("Date", "Receipts"),
row.names = c(NA, 10L),
class = c("tbl_df", "tbl", "data.frame"))
library(xts)
x <- xts(d[,2, drop=FALSE], order.by=as.Date(d[,1]))
library(dygraphs)
dygraph(x)
这是发布的结构,使用xts
作为索引类型快速转换为Date
。
我们已经完成了。如图所示,第一次观察显示为4月14日。
希望这有帮助。
答案 1 :(得分:0)
上周我再次开始开发这个应用程序时,我刚刚回到了这个问题,我终于能够解决它了。在我最初编写的代码中,问题必须特别与 valueFormatter
函数的 dyAxis()
属性中的 JavaScript 函数有关,我使用该函数为 dygraph
时间序列(此代码未在我的原始问题中显示)。在我 2017 年的代码中,我有:
dyAxis("x", valueFormatter = "function(ms) {
return new Date(ms).toDateString()}",
rangePad=5
)
其中 ms
是“自 1970 年 1 月 1 日午夜以来经过的毫秒数,UTC”(如 here 所述)。该数字源自 xts
对象的行索引(日期)。据我了解,Chrome(和 Opera)根据本地时区自动解释函数 toDateString()
(无论 xts 索引和从它派生的毫秒数是否明确为 UTC),而 Firefox 和 Safari 解释根据 UTC 的数字。 (我了解到 Chrome 和 Firefox here 之间的不同行为。)
我的解决方案是在 dygraph
的函数中明确构建 valueFormatter
图例的日期(这也允许我控制输出的日期格式):
dyAxis("x", valueFormatter = "function(ms) {
dow = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
temp = new Date(ms);
day = dow[temp.getUTCDay()];
date = temp.getUTCDate().toString();
month = months[temp.getUTCMonth()];
year = temp.getUTCFullYear().toString();
legend = day + ', ' + date + ' ' + month + ' ' + year;
return legend
}",
rangePad=5
)
使用 getUTCDay()
和 getUTCMonth()
可确保从 ms
派生的日期和月份数字是 UTC,无论浏览器如何。
就我能够在 Chrome、Opera、Firefox、Safari 和 RStudio 浏览器中进行测试而言,此解决方案有效。我希望其他人可能会觉得这很有用。我向 Dirk Eddelbuettel 道歉,因为他在 2017 年没有理解他的回答!