Dygraph.WEEKLY маркировка использует понедельники как тики в R

Я собираю еженедельные данные, используя dygraphs. dygraphs автоматически выбирает недельную ось по умолчанию. Тем не менее, я надеюсь, что есть способ, чтобы ось по умолчанию (воскресенье) совпала с моими данными (по понедельникам).

# Required packages
library("magrittr")
library("dygraphs")
library("xts")

# Data
daily <- structure(c(4000, 5000, 3000, 7000, 2000, 5000, 7000, 
                   2000, 3000, 6000, 5000, 9000, 2000, 2000, 2000, 
                   7000, 9000, 2000, 1000, 13000), .Dim = c(10L, 2L), .Dimnames = list(
                     NULL, c("col1", "col2")), index = structure(c(1476032400, 
                                                                   1476637200, 1477242000, 1477846800, 1478451600, 1479056400, 1479661200, 
                                                                   1480266000, 1480870800, 1481475600), tzone = "Asia/Saigon", tclass = c("POSIXct", 
                                                                                                                                          "POSIXt")), class = c("xts", "zoo"), .indexCLASS = c("POSIXct", 
                                                                                                                                                                                               "POSIXt"), tclass = c("POSIXct", "POSIXt"), .indexTZ = "Asia/Saigon", tzone = "Asia/Saigon")

# Graph
dygraph(daily, main = "Stackoverflow") %>%
  dyRangeSelector() %>%
  dyOptions(useDataTimezone = TRUE) 

dygraph render

Ответ 1

Вы можете попробовать использовать пользовательскую функцию ticker, которая начинается в первый день ваших данных и помещает галочку каждые семь дней.

Вот пример, вдохновленный функцией dygraph-tickers.js Dygraph.getDateAxis:

dygraph(daily, main = "Stackoverflow") %>%
  dyRangeSelector() %>%
  dyAxis("x",ticker='function(start_time, end_time, pixels, opts, dygraph, vals) {
         var formatter = opts("axisLabelFormatter");
         var ticks = [];
         var t;
         //spacing is a week in milliseconds
         var spacing = 1000 * 604800;

         for (t = start_time; t <= end_time; t += spacing) {
          ticks.push({ v:t,
         label: formatter(new Date(t), Dygraph.WEEKLY, opts, dygraph)
         });
         }
         return ticks;
   }') %>%
  dyOptions(useDataTimezone = TRUE)

Ответ 2

Обходным путем для этого было бы переформатирование значений метки dyAxis с помощью функций JavaScript (конечно, учитывая, что единственное, что вам нужно - это изменить первый день недели по умолчанию).

Посмотрите:

# libs and daily object ...

# the x values are passed as milliseconds, turn them into a date and extract day and month
getMonthDay <- 'function(d) {
  var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  var date;
  if (typeof d == "number") { // value
    date = new Date(d);
  } else { // label
    date = new Date(d.toString().substring(0, 15));
  }
  date.setDate(date.getDate() + 1);
  return date.getUTCDate() + " " + monthNames[date.getMonth()];
}'

# Graph
dygraph(daily, main = "Stackoverflow") %>%
  dyRangeSelector() %>%
  dyAxis(
    "x",
    valueFormatter = JS(getMonthDay),
    axisLabelFormatter = JS(getMonthDay),
    rangePad = 40 # the rangePad would adapt by itself
  )  %>%
  dyOptions(useDataTimezone = TRUE)

Обратите внимание, что мы имеем условие для проверки type объекта d. Это потому, что

Итак, в случае, если параметр d:

  • a number (valueFormatter), мы просто создаем новый объект date;
  • a object (axisLabelFormatter) - да, он отправляет параметр как object; поэтому нам нужно преобразовать его в правильный date.

Подход substring() необходим, потому что dygraphs отправляет объект следующим образом:

Sun Oct 09 2016 00:00:00 GMT+0700

... и из-за времени 00, как только вы попытаетесь конвертировать в дату, JavaScript вернет

Sat Oct 08 2016 14:00:00 GMT-0300 (Local Standard Time)

Таким образом, мы всегда будем рассматривать только день, месяц и год. Кроме того, вы бы правильно применили rangePad:

введите описание изображения здесь