I'm graphing weekly data using the dygraphs
package. dygraphs
automatically selects a weekly default axis. However, I'm hoping there is a way to have the default axis (Sundays) line up with my data (Mondays).
# 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)
You can try using a custom ticker
function that starts on the first day of your data and places a tick every seven days.
Here's an example inspired from the dygraph-tickers.js
Dygraph.getDateAxis
function:
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)
A workaround for this would be reformatting dyAxis
label values via JavaScript functions (of course, considering that the only thing you need is changing the default first day of the week).
Take a look:
# 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)
Note that we have a condition to check the type
of the d
object. That's because the
valueFormatter
- returns the valueOf
the date object;axisLabelFormatter
- returns the actual date
itselfSo, in case d
parameter is:
number
(valueFormatter), we simply create a new Date
object;object
(axisLabelFormatter) - yes, it sends the param as an Object
; so, we need to convert it to a proper Date
.The substring()
approach is needed because dygraphs sends the object like this:
Sun Oct 09 2016 00:00:00 GMT+0700
... and, because of the 00's time, once you try to convert to a date, JavaScript will return
Sat Oct 08 2016 14:00:00 GMT-0300 (Local Standard Time)
This way, we'll always consider only the day, month and year for that. Also, you'd have the rangePad
being applied properly:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With