Dygraph with multiple series at different time intervals - r

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.

Related

Plotting/Mutating Data on R

I've trying to plot data that has been mutated into quarterly growth rates from nominal levels.
i.e the original dataset was
Date GDP Level
2010Q1 457
2010Q2 487
2010Q3 538
2010Q4 589
2011Q1 627
2011Q2 672.2
2011Q3 716.4
2011Q4 760.6
2012Q1 804.8
2012Q2 849
2012Q3 893.2
2012Q4 937.4
Which was in an excel file which I have imported using
dataset <- read_excel("xx")
Then, I have done the below in order to mutate it to quarter on quarter growth ("QoQ Growth):
dataset %>%
mutate(QoQ Growth= (GDP Level) / lag(GDP Level, n=1) - 1)
I would like to now plot this % growth across time, however I'm not too sure how what the geom_line code is for a mutated variable, any help would be really truly appreciated! I'm quite new to R and really trying to learn, thanks!
Something like this?
library(tidyverse)
df %>%
mutate(QoQGrowth = (GDPLevel) / lag(GDPLevel, n=1) - 1) %>%
ggplot(aes(factor(Date), QoQGrowth, group=1)) +
geom_line()
Output
Data
df <- structure(list(Date = c("2010Q1", "2010Q2", "2010Q3", "2010Q4",
"2011Q1", "2011Q2", "2011Q3", "2011Q4", "2012Q1", "2012Q2", "2012Q3",
"2012Q4"), GDPLevel = c(457, 487, 538, 589, 627, 672.2, 716.4,
760.6, 804.8, 849, 893.2, 937.4)), class = "data.frame", row.names = c(NA,
-12L))
Package zoo defines a S3 class "yearqtr" and has a function to handle quarterly dates, as.yearqtr. Combined with ggplot2's scale_x_date, the formating of quarterly axis labels becomes easier.
dataset <- read.table(text = "
Date 'GDP Level'
2010Q1 457
2010Q2 487
2010Q3 538
2010Q4 589
2011Q1 627
2011Q2 672.2
2011Q3 716.4
2011Q4 760.6
2012Q1 804.8
2012Q2 849
2012Q3 893.2
2012Q4 937.4
", header = TRUE, check.names = FALSE)
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(zoo))
library(ggplot2)
dataset %>%
mutate(Date = as.yearqtr(Date, format= "%Y Q%q"),
Date = as.Date(Date)) %>%
mutate(`QoQ Growth` = `GDP Level` / lag(`GDP Level`, n = 1) - 1) %>%
ggplot(aes(Date, `QoQ Growth`)) +
geom_line() +
scale_x_date(date_breaks = "3 months", labels = as.yearqtr) +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))
#> Warning: Removed 1 row(s) containing missing values (geom_path).
Created on 2022-03-08 by the reprex package (v2.0.1)
Convert dataset to a zoo object z, use diff.zoo to get the growth, QoQ Growth, and then use autoplot.zoo with scale_x_yearqtr.
library(zoo)
library(ggplot2)
z <- read.zoo(dataset, FUN = as.yearqtr)
`QoQ Growth` <- diff(z, arith = FALSE) - 1
autoplot(`QoQ Growth`) +
scale_x_yearqtr(format = "%YQ%q", n = length(`QoQ Growth`)) +
xlab("")

How to add a label to a dygraph mouseover in 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))

How to merge similar date in HTML using R

I have a dataframe in R which looks like.
Order Date Sell Sell_pc Order_fm mkt_pc Dealer_pc
2020-01-01 5 14.34 340 11.23 23.43
2020-01-01 1000 14.34 45900 13.23 34.45
2020-01-02 12 12.33 13 15.44 23.66
2020-01-02 13000 11.45 600000 15.21 14.44
2020-01-03 110000 12.33 31 15.34 12.34
2020-01-03 1600 11.45 18000 13.31 24.45
I want to convert the above-mentioned data frame in HTML image in R, Where I want to merge to similar date in on in the same sequence and add a light gray column for every two-column skipping next two-column.
Required output like:
I have tried:
html_image<-df %>% tableHTML(rownames = FALSE,
widths = rep(100, 6),
caption = "Order Book Reported") %>%
add_css_caption(css = list(c("font-weight", "border","font-size"),
c("bold", "1px solid black","16px")))%>%
add_css_row(css = list(c("background-color"), c("lightgray")), rows = 0:2)
The gt-package could be helpful here:
library(gt)
library(tidyverse)
df |>
mutate(Date = as.Date(Date)) |>
group_by(Date) |>
gt() |>
# gt(rowname_col = "Date") |>
tab_stubhead(label = "Date") |>
tab_header(
title = md("Order Book Reported")
) |>
tab_options(
row_group.as_column = F,
row_group.background.color = "gray",
heading.background.color = "orange",
column_labels.background.color = "orange"
) |>
tab_options(row_group.as_column = TRUE) |>
tab_style(
style = list(
cell_fill(color = "grey")
),
locations = cells_body(
rows = Date == "2020-01-02"
)
)

ploting time series with day time in horizontal axis

Hi there I have some working code that selects data from a single station and plots it as a time series.in this data is a date time of the format:
28 11AC068 2018-08-30T02:15:00-06:00
29 11AC068 2018-08-30T02:20:00-06:00
file = "http://dd.weather.gc.ca/hydrometric/csv/SK/hourly/SK_hourly_hydrometric.csv"
skdat <- read.csv(file, head=T, sep=",", dec=".")
skdate <- skdat
colnames(skdat) <- c("ID", "Date", "Water.Level", "Grade.1", "Symbol.1",
"QA/QC-1", "Discharge/Debit", "Grade.2", "Symbol.2",
"QA/QC-2")
#There are 151 Factors of ID
str(skdat$ID)
skdat$Date <- as.Date(skdat$Date, "%h/%m")
#"05AH050","05EF001"#,..: 151 151 151 151 151 151 151 151 151 151 ...
plot.ts(subset(skdat, skdat$ID=='05EF001')$Water.Level, main="Plot TS of ID = 05EF001")
axis.Date(1, at=seq(min(skdat$Date), max(skdat$Date), by="hour"), format="%h-%m")
in the subset the date time is filtered out is there any way to keep that column in the data and use it to plot the horizontal axis just as hour min?
You could try something like this.
library(tidyverse)
file = "http://dd.weather.gc.ca/hydrometric/csv/SK/hourly/SK_hourly_hydrometric.csv"
skdat <- read.csv(file, head=T, sep=",", dec=".", stringsAsFactors = F)
colnames(skdat) <- c("ID", "Date", "Water.Level", "Grade.1", "Symbol.1",
"QA/QC-1", "Discharge/Debit", "Grade.2", "Symbol.2",
"QA/QC-2")
skdat %>% filter(ID=='05EF001') %>%
mutate(Date = gsub("-06:00$", "", Date) %>% lubridate::parse_date_time(., orders = "ymd HMS")) %>%
ggplot(aes(Date, Water.Level))+
geom_line()+
scale_x_datetime(breaks = "4 hours", date_labels = "%H:%M")
Created on 2018-09-01 by the reprex
package (v0.2.0).

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()
}

Resources