How to add a label to a dygraph mouseover in R? - r

I have been trying to plot a time series using dygraph in R. It seems that we can only pass in a dataframe with the dates and their values. All other columns will be automatically ignored. Here I have reproduced my data and the resulting graph:
library(dygraphs)
library(tidyverse)
library(plotly)
library(data.table)
dates <- seq(as.POSIXct("2021-01-01 05:00:00"), as.POSIXct("2021-01-05 05:00:00"), by = 8*3600)
df <- data.table(date = dates,
percentage = round(runif(length(dates), min = 0, max = 1), digits = 2),
team = sample(c("A", "B", "C", "D", "E"), size = length(dates), replace = T)
)
dygraph(df) %>%
dyOptions(drawPoints = T, pointSize = 3) %>%
dyAxis(name = "y", label = "percentage") %>%
dyLegend(show = "follow")
And here how the graph looks like:
As we can see the team corresponding to each date is not shown in the legend. I would like to see the teams on mouseover. To be more clear, I could manage to do this using ggplot and ggplotly, however, the plotly package is relatively heavy and I would still like to use dygraph for my Shiny application. Here how it would look like using ggplotly:
p <- ggplot(df, aes(x = date, y = percentage)) + geom_line() + geom_point(aes(group = team))
ggplotly(p)
Is there any way I could add labels to a dygraph and achieve the same thing? I would appreciate any help

You could create a custom valueFormater:
valueFormatter <- function(df) {
paste0('function(x){return ',
paste0((paste0('x==',as.numeric(head(df$date,-1))*1000,' ? "',head(df$date,-1),' - Team ',head(df$team,-1),'"',collapse = ":")),
': "',tail(df$date,1),' Team ',tail(df$team,1)),'";}')
}
Dates are tricky as they are counted in milliseconds in JavaScript, hence the as.numeric(head(df$date,-1))*1000.
The formatter generates a JavaScript function using ifelse shorthand ternary operator:
cat(valueFormatter(df))
function(x){return x==1609473600000 ? "2021-01-01 05:00:00 - Team A":x==1609502400000 ? "2021-01-01 13:00:00 - Team C":x==1609531200000 ? "2021-01-01 21:00:00 - Team E":x==1.60956e+12 ? "2021-01-02 05:00:00 - Team E":x==1609588800000 ? "2021-01-02 13:00:00 - Team A":x==1609617600000 ? "2021-01-02 21:00:00 - Team C":x==1609646400000 ? "2021-01-03 05:00:00 - Team D":x==1609675200000 ? "2021-01-03 13:00:00 - Team C":x==1.609704e+12 ? "2021-01-03 21:00:00 - Team B":x==1609732800000 ? "2021-01-04 05:00:00 - Team A":x==1609761600000 ? "2021-01-04 13:00:00 - Team B":x==1609790400000 ? "2021-01-04 21:00:00 - Team C": "2021-01-05 05:00:00 Team C";}
This function can be used by dyGraphs via the valueFormatter argument :
dygraph(df[,.(date,percentage)]) %>% dyOptions(drawPoints = T, pointSize = 3) %>%
dyAxis('x',valueFormatter = valueFormatter(df))

Related

How to highlight time series in some date ranges in R

I need to highlight some dates ranges in my time series chart, but I can´t go ahead.
The dataset used is following:
library(dplyr)
library(xts)
library(zoo)
df <- read.csv("https://github.com/rhozon/datasets/raw/master/dataset_1a.csv", header = TRUE, sep =",") %>%
mutate(
dates = as.Date(dates)
) %>%
filter(
dates >= "2019-01-01"
) %>%
glimpse()
df_xts <- xts(df[,-1, drop = FALSE], order.by = df[,1]) %>% as.xts()
class(df_xts)
head(df_xts)
Then I tryed the following PerfomanceAnalytics commands:
library(PerformanceAnalytics)
# Create period to hold the 3 months of 2020
period <- c("2020-01/2020-03")
# Highlight the first three months of 2020
chart.TimeSeries(df$prices_usa, period.areas = period, period.color = "lightgrey")
with no success...
Error in try.xts(x, error = "'x' needs to be timeBased or xtsible") :
'x' needs to be timeBased or xtsible
By using the dygraphs package...
library(dygraphs)
dygraph( df$prices_usa ) %>%
dyShading(from = "2020-06-30", to = "2020-09-01") %>%
dyAnnotation("2020-08-01", text = "X", tooltip = "date range") %>%
dyAxis("x", drawGrid = TRUE) %>%
dyEvent("2020-06-30", "Jul 2020", labelLoc = "bottom") %>%
dyEvent("2020-09-01", "Sep 2020", labelLoc = "bottom") %>%
dyOptions(drawPoints = FALSE, pointSize = 2) #%>%
And again I found another issue:
Error in dygraph(df$prices_usa) : Unsupported type passed to argument 'data'.
I didn´t tryed with the ggplot2 package because I need to use it with interaticvity.
Could someone recommend me a solution to these issues or something that is simpler to do (even with ggplot2+plotly) that can be useful for me to demarcate or highlight some ranges of dates/periods in my time series graphs?
Using the reproducible xts object in the Note at the end use plot and xblocks. To specify a different color use something like adjustcolor("blue", 0.2) in place of grey(...). For many other approaches google R shading recessions
library(xts)
plot(as.zoo(aapl))
xblocks(aapl, ifelse(time(aapl) %in% time(aapl[period]), grey(.2, .2), NA))
Note
library(quantmod)
getSymbols("AAPL")
period <- "2020-01/2020-03"
aapl <- Cl(AAPL)

Dygraph with multiple series at different time intervals

I have 2 sets of time series with different time intervals which I am attempting to show in a single dygraph plot;
Stage (river level) and Modelled Stage - 5 or 15 minute interval
Rainfall and Forecast Rainfall - 3 hourly interval
I would like the stage set to be a line chart and rainfall to appear as a step plot similar to below.
My issue is that, as far as I can see, you must cbind your timeseries together in order to create a multi-series dygraph. Cbind fills in 'missing' points with NA causing my graph to appear with isolated points of rainfall like so
Is there any way to overplot in dygraph without combining everything into 1 time series object? Alternatively does anybody have any clever methods for filling in NAs during a cbind? I have a rather inelegant bit of code to fill in NAs after the cbind at the moment...
Example code for second plot
stage <- zoo(sample(1:100, 154, replace=TRUE), seq(as.POSIXct("2018-08-23"), as.POSIXct("2018-08-31"), by = 4500))
rain <- zoo(sample(1:100, 154, replace=TRUE), seq(as.POSIXct("2018-08-23"), as.POSIXct("2018-08-31"), by = 54000))
eventData <- cbind(stage, rain)
dygraph(eventData, main = "Sitename") %>%
dyOptions(useDataTimezone = TRUE, colors = colour, drawGrid = F) %>%
dyAxis("y", label = "Stage", valueRange = c(0, maxStage+maxStage*.2), independentTicks = TRUE) %>%
dyAxis("y2", label = "Rainfall ", valueRange = c(0, maxRain+maxRain*.5), independentTicks = TRUE) %>%
dySeries("Stage", axis=('y')) %>%
dySeries("Rainfall", axis=('y2'), stepPlot = T, fillGraph = T) %>%
You can use zoo::na.locf function to fill the missing rows.
In your example:
stage <- zoo(sample(1:100, 154, replace=TRUE), seq(as.POSIXct("2018-08-23"), as.POSIXct("2018-08-31"), by = 4500))
rain <- zoo(sample(1:100, 154, replace=TRUE), seq(as.POSIXct("2018-08-23"), as.POSIXct("2018-08-31"), by = 54000))
eventData <- cbind(stage, rain)
head(eventData)
stage rain
2018-08-23 00:00:00 85 61
2018-08-23 01:15:00 71 NA
2018-08-23 02:30:00 10 NA
2018-08-23 03:45:00 16 NA
2018-08-23 05:00:00 31 NA
2018-08-23 06:15:00 92 NA
# fill NAs with na.locf
eventData <- na.locf(eventData)
head(eventData)
stage rain
2018-08-23 00:00:00 85 61
2018-08-23 01:15:00 71 61
2018-08-23 02:30:00 10 61
2018-08-23 03:45:00 16 61
2018-08-23 05:00:00 31 61
2018-08-23 06:15:00 92 61
This can be plotted the way you want it:
library(dygraphs)
dygraph(eventData, main = "Sitename") %>%
dyOptions(drawGrid = F) %>%
dyAxis("y", label = "Stage", independentTicks = TRUE) %>%
dyAxis("y2", label = "Rainfall ", independentTicks = TRUE) %>%
dySeries("stage", axis=('y')) %>%
dySeries("rain", axis=('y2'), stepPlot = T, fillGraph = T)
See also here for a deeper discussion about filling NAs.

Weekly data plot in R

I have a big data frame (from 2007 to 2015), with data points at about every 2 minutes. I want to plot the graph of every week (from 2007 to 2015), with each week being automatically exported as a PNG file to my computer's folder. Previously, I was able to successfully produce working codes for annually, monthly, and daily plot. E.g.for yearly data:
for(j in 2007:2015){
mypath <- file.path("~", "Documents","Yearly", paste("WAO_AIR_Data_", j, ".png", sep = "" ))
png(filename = mypath, width = 963, height = 690)
timePlot(selectByDate(new_subdata, year = j),
pollutant = c("CO2", "O2", "APO"),
date.pad = TRUE,
pch = c(19,19,19),
cex = 0.2,
xlab = paste("Month of year in", j),
ylab = "CO2, O2, and APO concentrations",
name.pol = c("CO2 (ppm)", "O2 (per meg)", "APO (per meg)"),
)
dev.off()
}
The data frame looks like this
tail(new_subdata)
date CO2 O2 APO
1052042 2015-12-31 23:48:45 409.636 -666.39 -353.27
1052043 2015-12-31 23:50:46 409.652 -669.62 -356.41
1052044 2015-12-31 23:52:44 409.679 -669.44 -356.09
1052045 2015-12-31 23:54:46 409.703 -667.07 -353.59
1052046 2015-12-31 23:56:44 409.719 -671.02 -357.46
1052047 2015-12-31 23:58:46 409.734 NA NA
But I dont know how to produce the code for weekly plotting. Can anyone help me please? Thank you so much!
Via ?strptime, you can get the week out of a Date or POSIXct with %U
%U
Week of the year as decimal number (00–53) using Sunday as the first day 1 of the week (and typically with the first Sunday of the year as day 1 of week 1). The US convention.
x <- Sys.time()
class(x); format(x, '%U')
# [1] "POSIXct" "POSIXt"
# [1] "26"
x <- Sys.Date()
class(x); format(x, '%U')
# [1] "Date"
# [1] "26"
Using your example data with minor changes:
new_subdata <- read.table(header = TRUE, text = "date CO2 O2 APO
1052042 '2015-10-31 23:48:45' 409.636 -666.39 -353.27
1052043 '2015-10-31 23:50:46' 409.652 -669.62 -356.41
1052044 '2015-11-30 23:52:44' 409.679 -669.44 -356.09
1052045 '2015-11-30 23:54:46' 409.703 -667.07 -353.59
1052046 '2015-12-31 23:56:44' 409.719 -671.02 -357.46
1052047 '2015-12-31 23:58:46' 409.734 NA NA")
## create a new grouping variable with year/week
new_subdata <- within(new_subdata, {
yr_wk <- format(as.Date(date), '%Y %U')
})
## iterate over the unique values
jj <- unique(new_subdata$yr_wk)
# [1] "2015 43" "2015 48" "2015 52"
## do some plotting
par(mfrow = n2mfrow(length(jj)), las = 1, mar = c(5,6,2,2),
tcl = .2, mgp = c(3,.25,0))
xr <- range(new_subdata$O2, na.rm = TRUE)
yr <- range(new_subdata$CO2, na.rm = TRUE)
for (j in jj) {
mypath <- file.path("~", "Documents","Yearly", sprintf("WAO_AIR_Data_%s.png", j))
# png(filename = mypath, width = 963, height = 690)
plot(CO2 ~ O2, data = subset(new_subdata, yr_wk == j), xlim = xr, ylim = yr)
# dev.off()
}

Analyse day-time of a date-time variable

This is how I solved the problem:
datestimes <- c("2014-01-01 23:03:00", "2014-01-02 00:35:00", "2014-01-02 00:51:00") # There is a change in date.
# Is there any lubridate command for the following step?
time <- as.POSIXct(strftime(datetimes, format = "%H:%M:%S", tz = "UTC"), format = "%H:%M:%S")
time
[1] "2016-05-13 23:03:00 CEST" "2016-05-13 00:35:00 CEST" "2016-05-13 00:51:00 CEST"
Is there a reason that there is no such functionality in lubridate?
As I said - I am only interested in the time part - not the date.
lubridate::hms gives periods:
ltime <- lubridate::hms(strftime(datetimes, format = "%H:%M:%S", tz = "UTC"))
ltime
[1] "23H 3M 0S" "35M 0S" "51M 0S"
class(ltime)
[1] "Period"
attr(,"package")
[1] "lubridate"
What about this?
library(lubridate)
datetimes <- c("2014-01-01 23:03:00", "2014-01-02 00:35:00", "2014-01-02 00:51:00")
dataset <- data.frame(
time = as.POSIXct(strftime(datetimes, format = "%H:%M:%S", tz = "UTC"), format = "%H:%M:%S")
)
dataset$delta <- dataset$time - floor_date(dataset$time, unit = "day")
dataset$relative <- as.POSIXct("2001-01-01 0:0:0") + minutes(dataset$delta)
library(ggplot2)
ggplot(dataset, aes(x = relative)) +
geom_histogram(binwidth = 3600) +
scale_x_datetime(date_breaks = "3 hour", date_labels = "%H:%M")
Thanks to alistair: ymd_hms(paste(today(), format(ymd_hms(datetimes), '%T'))) will be my choice. This can be nicely combined with hist or ggplot2 (See above).

Time series in rHighchart date format issues

I'd like to display a time series as a highchart interactive graphic. However, in the following R scrip the dates are not displayed correctly all. The numerical value for the date is cut after five digits, making them appear all on the same day and time.
Anyone experienced and solved something similar?
library(plyr)
library(rCharts)
library(rHighcharts)
cs <-c("13-10-30 12:30:00", "13-10-30 12:35:00", "13-10-30 12:40:00",
"13-10-30 12:45:00", "13-10-30 12:50:00", "13-10-30 12:55:00")
x <-strptime(cs, "%y-%m-%d %H:%M:%S")
dfr <-data.frame(date=as.POSIXct(x,origin="1970-01-01"),
value=c(1.5,1.25,.75,2.1,1.3,1.4))
hpl <- hPlot(
value~date,
data = dfr,
type = "scatter"
)
hpl$xAxis(type = "datetime")
hpl$chart(zoomType = "x")
hpl$plotOptions(
line = list(
marker = list(enabled = F)
)
)
hpl

Resources