简体   繁体   English

dygraph 中的日期(使用 R 和 xts)显示比数据早一天

[英]Date in dygraph (using R and xts) shows one day earlier than data

This is my first stackoverflow question, so apologies in advance for any lapses in etiquette or presentation.这是我的第一个 stackoverflow 问题,因此对于礼仪或演示中的任何失误提前道歉。

I am using the dygraphs() package in R (3.3.3 on a Mac running Mavericks, using RStudio) to graph a time series of box-office receipts from an 18th-century theater.我正在使用 R 中的 dygraphs() 包(运行 Mavericks 的 Mac 上的 3.3.3,使用 RStudio)绘制 18 世纪剧院票房收入的时间序列图。 The dates run from 1789-04-14 to 1791-03-07.日期从 1789-04-14 到 1791-03-07。 I'm using the newest version of the xts package (0.10-0), but the problem was identical in the previous version.我使用的是最新版本的 xts 包 (0.10-0),但问题与之前的版本相同。 As an xts object the data looks like this:作为 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

The dates imported for the index are of type date .为索引导入的日期是date类型。 ('kr' stands for 'kreuzer,' a subdivision of the monetary unit of account at the time.) (“kr”代表“kreuzer”,是当时货币记账单位的细分。)

The code to create the dygraph is:创建 dygraph 的代码是:

dygraph(receipts.xts, 
        main = "Opera Receipts, Burgtheater, 1789-1791") %>%
  dySeries("kr", label = "Receipts (kr)") %>% 
  dyLegend(show="always", hideOnMouseOut =FALSE) %>% dyRangeSelector()

All dates in the legend show one day earlier than the corresponding date in the xts object.图例中的所有日期都比 xts 对象中的相应日期早一天显示。 This is shown in the attached screenshot, where the first datapoint is 1789-04-14, but shows in the RStudio viewer in the legend as "Apr, 13, 1789" (I have not been able to find a way to get rid of the unwanted comma after the month abbreviation.)这显示在随附的屏幕截图中,其中第一个数据点是 1789-04-14,但在图例中的 RStudio 查看器中显示为“1789 年 4 月 13 日”(我一直无法找到摆脱的方法月份缩写后不需要的逗号。)

示例 dygraph 在图例中显示不正确的日期

Oddly, when I save this graph as html, the legend on the webpage shows the correct date!奇怪的是,当我将此图表另存为 html 时,网页上的图例显示了正确的日期!

I've tried a very wide variety of possible solutions, but nothing so far has worked.我尝试了多种可能的解决方案,但到目前为止都没有奏效。 This looks like a bug, but it's not clear to me where the bug is (in the dygraphs package? in RStudio? in xts?).这看起来像一个错误,但我不清楚错误在哪里(在 dygraphs 包中?在 RStudio 中?在 xts 中?)。 My question seems similar to this one:我的问题似乎与此类似:

Date bug in dygraph in dygraphs package (using JavaScript) in R R中dygraphs包(使用JavaScript)中dygraph中的日期错误

But that question seems never to have had a definitive answer.但这个问题似乎从未有过明确的答案。 The only way I can get the proper dates to display in the legends in the RStudio viewer is to add one day to all the dates (using lubridate) that are used as the index of the xts object, but then the dates are incorrect in the html.我可以获得正确日期以显示在 RStudio 查看器的图例中的唯一方法是将一天添加到用作 xts 对象索引的所有日期(使用 lubridate),但是日期在HTML。

**** Edit on 7/10/17 in response to Dirk's reply **** **** 于 2017 年 7 月 10 日编辑以回应德克的回复 ****

I'd already been aware of the potential of the "hidden" timezone problem with the dates, and had tried a number of other approaches to fix that, although not yet setting the timezone with Sys.setenv() as Dirk suggested.我已经意识到日期的“隐藏”时区问题的可能性,并且尝试了许多其他方法来解决这个问题,尽管还没有像德克建议的那样使用Sys.setenv()设置时区。 I just tried that, and it doesn't fix the problem either.我刚刚试过了,它也没有解决问题。 My steps this time were:我这次的步骤是:

operas$Date <- as.character(operas$Date)
Sys.setenv(tz="UTC")
receipts.xts <- xts(operas$Receipts, as.Date(operas$Date))
colnames(receipts.xts) <- "kr"

(In the originating dataframe the dates are already of date type, but I wanted to start from scratch in showing this problem.) The dygraphs code is then the same as in my original example. (在原始数据框中,日期已经是date类型,但我想从头开始显示这个问题。) dygraphs代码与我原来的示例相同。

The results are identical: dates in the legend are one day too early when examined in the RStudio viewer , but are correct in the exported html when viewed in a browser.结果是相同的:在RStudio 查看器中检查时图例中的日期为时过早一天,但在浏览器中查看时导出的 html 中的日期是正确的。

So it looks like the problem is probably somewhere else.所以看起来问题可能出在其他地方。

The use of lubridate 's as_date() in my original example only reflected one of my more recent attempts at a fix.在我的原始示例中使用lubridateas_date()仅反映了我最近的修复尝试之一。 My original code had used as.Date().我的原始代码使用了 as.Date()。 But thanks for the pointer.不过谢谢指点。

**** Some sample data **** **** 一些示例数据 ****

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

So let's do a little tutorial.所以让我们做一个小教程。 Start with a date, convert to a POSIXct and then format:以日期开头,转换为 POSIXct,然后格式化:

R> format(as.POSIXct(as.Date("2017-07-08")))
[1] "2017-07-07 19:00:00"
R> 

See what happens?走着瞧吧? I am in Chicago, and the five hours subtracted from midnight are my offset to UTC.我在芝加哥,从午夜减去五个小时是我对 UTC 的偏移量。 One possible fix is to set the timezone to UTC:一种可能的解决方法是将时区设置为 UTC:

R> Sys.setenv(TZ="UTC")
R> format(as.POSIXct(as.Date("2017-07-08")))
[1] "2017-07-08"
R> 

Now the same input data is correctly "printed" as the same date.现在相同的输入数据被正确地“打印”为相同的日期。

Lesson: Be wary of Date to POSIXct conversions.教训:警惕DatePOSIXct的转换。 All you needed here is the proper timezone (for the context of the formatting).您在这里只需要正确的时区(用于格式化上下文)。

Lastly, you really do not need the lubridate package to adjust a date.最后,你真的不需要 lubridate 包来调整日期。 R itself does that just fine: 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> 

Dates and times are challenging for programmers and users.日期和时间对程序员和用户来说是一个挑战。 R has great support. R 有很大的支持。 Take your time and learn it, one issue at a time.花点时间学习它,一次一个问题。

Edit: Ok, after I got dragged into this again, here are code and a chart.编辑:好的,在我再次被拖入其中之后,这里有代码和图表。

Code代码

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)

This is the structure as posted, quickly converted to an xts using Date as the index type.这是发布的结构,使用Date作为索引类型快速转换为xts

And we're done.我们完成了。 As the chart shows, the first observation is shown as April 14 just as it should.如图表所示,第一个观察结果显示为 4 月 14 日。

Hope this helps.希望这可以帮助。

Chart图表

在此处输入图像描述

Data数据

在此处输入图像描述

I just recently returned to this question when I began working on this app again last week, and I've finally been able solve it.当我上周再次开始使用这个应用程序时,我最近才回到这个问题,我终于能够解决它。 In my code as I had originally written it, the problem had to do specifically with the JavaScript function in the valueFormatter attribute of the dyAxis() function that I used for constructing a legend for the dygraph time series (this code was not shown in my original question).在我最初编写的代码中,问题必须专门与dyAxis()函数的valueFormatter属性中的 JavaScript 函数有关,该函数用于为dygraph时间序列构建图例(此代码未显示在我的原始问题)。 In my code from 2017, I had:在我 2017 年的代码中,我有:

dyAxis("x", valueFormatter = "function(ms) {
                                 return new Date(ms).toDateString()}",
        rangePad=5
)

where ms is "the number of milliseconds that have elapsed since midnight on January 1, 1970, UTC" (as described here ).其中ms是“自 1970 年 1 月 1 日午夜以来经过的毫秒数,UTC”(如此所述)。 This number was derived from the row index (the date) of the xts object.此数字源自xts对象的行索引(日期)。 As I understand it, Chrome (and Opera) automatically interpret the function toDateString() according to the local timezone (regardless of whether the xts index and the number of milliseconds derived from it is explicitly UTC), whereas Firefox and Safari interpret the number according to UTC.据我了解,Chrome(和 Opera)根据本地时区自动解释函数toDateString() (不管 xts 索引和从中派生的毫秒数是否明确为 UTC),而 Firefox 和 Safari 则根据到协调世界时。 (I learned of the different behavior between Chrome and Firefox here .) (我在这里了解了 Chrome 和 Firefox 之间的不同行为。)

My solution is to build the date for the dygraph legend explicitly in the function for valueFormatter (which also allows me control over the date format of the output):我的解决方案是在valueFormatter函数中显式构建dygraph图例的日期(这也允许我控制输出的日期格式):

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
          )

Using getUTCDay() and getUTCMonth() makes sure that the day and month numbers derived from ms are UTC, regardless of browser.使用getUTCDay()getUTCMonth()确保从ms派生的日期和月份数字是 UTC,无论浏览器如何。

This solution works, so far as I've been able to test, in Chrome, Opera, Firefox, Safari, and the RStudio browser.据我测试,该解决方案在 Chrome、Opera、Firefox、Safari 和 RStudio 浏览器中有效。 I hope others may find this useful.我希望其他人会觉得这很有用。 My apologies to Dirk Eddelbuettel for not having understood his answer in 2017!我向 Dirk Eddelbuettel 道歉,因为我没有理解他在 2017 年的回答!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM