Add convenience bindings for ggplot2 and plotly with hyperlinks
These functions will probably be moved to a separate package.
Change-Id: Iaecd23b1401bc5df7ee4a904dca2e87466266143
diff --git a/DESCRIPTION b/DESCRIPTION
index 5e2ddf4..6faf7ee 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -22,6 +22,8 @@
lubridate,
curl,
jsonlite,
+ plotly,
+ htmlwidgets,
utils,
httr,
methods
diff --git a/NAMESPACE b/NAMESPACE
index 0e11e6f..4ba2e60 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -8,6 +8,7 @@
export(complete)
export(expand_grid)
export(geom_freq_by_year_ci)
+export(ggplotly)
export(group_by)
export(ipm)
export(mutate)
@@ -44,15 +45,23 @@
importFrom(dplyr,select)
importFrom(dplyr,starts_with)
importFrom(dplyr,summarise)
+importFrom(ggplot2,GeomPoint)
+importFrom(ggplot2,aes)
importFrom(ggplot2,element_text)
importFrom(ggplot2,geom_line)
importFrom(ggplot2,geom_point)
importFrom(ggplot2,geom_ribbon)
+importFrom(ggplot2,ggplot)
+importFrom(ggplot2,ggproto)
+importFrom(ggplot2,layer)
importFrom(ggplot2,scale_x_continuous)
importFrom(ggplot2,theme)
+importFrom(htmlwidgets,onRender)
+importFrom(htmlwidgets,saveWidget)
importFrom(jsonlite,fromJSON)
importFrom(lubridate,year)
importFrom(magrittr,"%>%")
+importFrom(plotly,ggplotly)
importFrom(purrr,map_dfr)
importFrom(stats,prop.test)
importFrom(tibble,as_tibble)
diff --git a/R/misc.R b/R/misc.R
index 9a97f22..b90841e 100644
--- a/R/misc.R
+++ b/R/misc.R
@@ -22,9 +22,17 @@
}
-#' Plot frequency by year graphs with confidence intervals
+## Mute notes: "Undefined global functions or variables:"
+globalVariables(c("conf.high", "conf.low", "onRender", "webUIRequestUrl"))
+
+
+#' Experimental: Plot frequency by year graphs with confidence intervals
#'
-#' Convenience function for plotting typical frequency by year graphs with confidence intervals using ggplot2.
+#' Experimental convenience function for plotting typical frequency by year graphs with confidence intervals using ggplot2.
+#' \bold{Warning:} This function may be moved to a new package.
+#'
+#' @param mapping Set of aesthetic mappings created by aes() or aes_(). If specified and inherit.aes = TRUE (the default), it is combined with the default mapping at the top level of the plot. You must supply mapping if there is no plot mapping.
+#' @param ... Other arguments passed to geom_ribbon, geom_line, and geom_click_point.
#'
#' @examples
#' library(ggplot2)
@@ -34,18 +42,95 @@
#' cbind(frequencyQuery(kco, "[tt/l=Heuschrecke]",
#' paste0(.$condition," & pubDate in ", .$year))) %>%
#' ipm() %>%
-#' ggplot(aes(year, ipm, fill = condition, color = condition, ymin = conf.low, ymax = conf.high)) +
+#' ggplot(aes(year, ipm, fill = condition, color = condition)) +
#' geom_freq_by_year_ci()
#'
-#' @importFrom ggplot2 geom_ribbon geom_line geom_point theme element_text scale_x_continuous
+#' @importFrom ggplot2 ggplot aes geom_ribbon geom_line geom_point theme element_text scale_x_continuous
#'
#' @export
-geom_freq_by_year_ci <- function() {
+geom_freq_by_year_ci <- function(mapping = aes(ymin=conf.low, ymax=conf.high), ...) {
list(
- geom_ribbon(alpha = .3, linetype = 0, show.legend = FALSE),
- geom_line(),
- geom_point(),
- theme(axis.text.x = element_text(angle = 45, hjust = 1)),
+ geom_ribbon(mapping,
+ alpha = .3, linetype = 0, show.legend = FALSE, ...),
+ geom_line(...),
+ geom_click_point(aes(url=webUIRequestUrl), ...),
+ theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = c(0.8, 0.2)),
scale_x_continuous(breaks = function(x) seq(ceiling(x[1]), floor(x[2]), by = 1 + floor(((x[2]-x[1])/30)))))
}
+#' @importFrom ggplot2 ggproto aes GeomPoint
+GeomClickPoint <- ggproto(
+ "GeomPoint",
+ GeomPoint,
+ required_aes = c("x", "y"),
+ default_aes = aes(
+ shape = 19, colour = "black", size = 1.5, fill = NA,
+ alpha = NA, stroke = 0.5, url = NA
+ ),
+ extra_params = c("na.rm", "url"),
+ draw_panel = function(data, panel_params,
+ coord, na.rm = FALSE, showpoints = TRUE, url = NULL) {
+ GeomPoint$draw_panel(data, panel_params, coord, na.rm = na.rm)
+ }
+)
+
+#' @importFrom ggplot2 layer
+geom_click_point <- function(mapping = NULL, data = NULL, stat = "identity",
+ position = "identity", na.rm = FALSE, show.legend = NA,
+ inherit.aes = TRUE, url = NA, ...) {
+ layer(
+ geom = GeomClickPoint, mapping = mapping, data = data, stat = stat,
+ position = position, show.legend = show.legend, inherit.aes = inherit.aes,
+ params = list(na.rm = na.rm, ...)
+ )
+}
+
+
+#' @importFrom htmlwidgets onRender
+tooltip2hyperlink <- function(p, attribute="webUIRequestUrl") {
+ pattern <- paste0(attribute, ": ([^<]+)")
+ for(i in grep(attribute, p$x$data)) {
+ x <- p[["x"]][["data"]][[i]][["text"]]
+ m <- regexpr(pattern, x)
+ matches <- sub(paste0(attribute, ": "), "", regmatches(x, m))
+ p$x$data[[i]]$customdata <- matches
+ p[["x"]][["data"]][[i]][["text"]] <- sub(paste0(attribute, ":[^<]*<br ?/?>"), "", p[["x"]][["data"]][[i]][["text"]] )
+ }
+ onRender(p, "function(el, x) { el.on('plotly_click', function(d) { var url=d.points[0].customdata; if(url) { window.open(url, 'korap') } })}")
+}
+
+#' Experimental: Convert ggplot2 to plotly with hyperlinks to KorAP queries
+#'
+#' \code{RKorAPClient::ggplotly} converts a \code{ggplot2::ggplot()} object to a plotly
+#' object with hyperlinks from data points to corresponding KorAP queries.
+#' \bold{Warning:} This function may be moved to a new package.
+#'
+#' @param p a ggplot object.
+#' @param tooltip a character vector specifying which aesthetic mappings to show
+#' in the tooltip. If you want hyperlinks to KorAP queries you need to include
+#' \code{"url"} here.
+#' @param ... Other arguments passed to \code{plotly::ggplotly}
+#'
+#' @examples
+#' library(ggplot2)
+#' kco <- new("KorAPConnection", verbose=TRUE)
+#' g <- expand_grid(condition = c("textDomain = /Wirtschaft.*/", "textDomain != /Wirtschaft.*/"),
+#' year = (2002:2018)) %>%
+#' cbind(frequencyQuery(kco, "[tt/l=Heuschrecke]",
+#' paste0(.$condition," & pubDate in ", .$year))) %>%
+#' ipm() %>%
+#' ggplot(aes(year, ipm, fill = condition, color = condition)) +
+#' ## theme_light(base_size = 20) +
+#' geom_freq_by_year_ci()
+#' p <- ggplotly(g)
+#' print(p)
+#' ## saveWidget(p, paste0(tmpdir(), "heuschrecke.html")
+#'
+#'
+#' @importFrom plotly ggplotly
+#' @importFrom htmlwidgets saveWidget
+#' @export
+ggplotly <- function(p = ggplot2::last_plot(), tooltip = c("x", "y", "colour", "url"), ...) {
+ pp <- plotly::ggplotly(p = p, tooltip = tooltip, ...)
+ tooltip2hyperlink(pp)
+}
diff --git a/Readme.md b/Readme.md
index 2071600..0cefd0e 100644
--- a/Readme.md
+++ b/Readme.md
@@ -33,10 +33,11 @@
library(RKorAPClient)
library(ggplot2)
kco <- new("KorAPConnection", verbose=TRUE)
-expand_grid(condition = c("textDomain = /Wirtschaft.*/", "textDomain != /Wirtschaft.*/"), year = (2002:2018)) %>%
+expand_grid(condition = c("textDomain = /Wirtschaft.*/", "textDomain != /Wirtschaft.*/"),
+ year = (2002:2018)) %>%
cbind(frequencyQuery(kco, "[tt/l=Heuschrecke]", paste0(.$condition," & pubDate in ", .$year))) %>%
ipm() %>%
- ggplot(aes(x = year, y = ipm, fill = condition, color = condition, ymin = conf.low, ymax = conf.high)) +
+ ggplot(aes(x = year, y = ipm, fill = condition, colour = condition)) +
geom_freq_by_year_ci()
```
![](man/figures/Readme-Example-1.png)<!-- -->
diff --git a/demo/alternativesOverTime.R b/demo/alternativesOverTime.R
index ae91ff5..dca55b3 100755
--- a/demo/alternativesOverTime.R
+++ b/demo/alternativesOverTime.R
@@ -11,19 +11,14 @@
df <- expand_grid(Variant = alternatives, year = years) %>%
cbind(corpusQuery(kco, .$Variant, sprintf("textType = /Zeit.*/ & pubDate in %d", .$year))) %>%
group_by(year) %>% mutate(tokens = sum(totalResults)) %>%
- ci()
- g <- ggplot(data = df, mapping = aes(x = year, y = f, color = Variant, fill = Variant, ymin = conf.low, ymax = conf.high)) +
+ ci() %>%
+ rename(share=f)
+ g <- ggplot(data = df, mapping = aes(x = year, y = share, colour = Variant, fill = Variant)) +
geom_freq_by_year_ci() +
ggtitle(paste0(alternatives, collapse = " vs. ")) +
xlab("TIME") +
ylab(sprintf("Observed frequency ratio"))
- pp <- ggplotly(g, tooltip = c("x", "y"))
- for (i in 1:length(alternatives)) {
- vdata <- df[df$Variant == alternatives[i],]
- pp$x$data[[2+i]]$customdata <- vdata$webUIRequestUrl
- pp$x$data[[2+i]]$text <- sprintf("%s<br />absolute: %d / %d", pp$x$data[[2+i]]$text, vdata$totalResults, vdata$tokens)
- }
- ppp <- onRender(pp, "function(el, x) { el.on('plotly_click', function(d) { var url=d.points[0].customdata; window.open(url, 'korap') })}")
+ ppp <- RKorAPClient::ggplotly(g)
print(ppp)
df
}
diff --git a/demo/conditionsOverTime.R b/demo/conditionsOverTime.R
index 9f0590d..b23d2bf 100644
--- a/demo/conditionsOverTime.R
+++ b/demo/conditionsOverTime.R
@@ -6,17 +6,19 @@
#install_git("https://korap.ids-mannheim.de/gerrit/KorAP/RKorAPClient", upgrade="never")
library(RKorAPClient)
library(ggplot2)
+library(plotly)
conditionsOverTime <- function(query, conditions, years, kco = new("KorAPConnection", verbose = TRUE)) {
g <- expand_grid(condition = conditions, year = years) %>%
cbind(frequencyQuery(kco, query, sprintf("%s & pubDate in %d", .$condition, .$year))) %>%
ipm() %>%
- ggplot(aes(x = year, y = ipm, fill=condition, color=condition, ymin=conf.low, ymax=conf.high)) +
+ ggplot(aes(x = year, y = ipm, fill=condition, color=condition)) +
geom_freq_by_year_ci() +
xlab("TIME") +
labs(color="Virtual Corpus", fill="Virtual Corpus") +
ylab(sprintf("Observed frequency/million of \u201c%s\u201d", query))
- print(g)
+ p <- RKorAPClient::ggplotly(g)
+ print(p)
}
conditionsOverTime("[tt/l=Heuschrecke]", c("textClass = /natur.*/", "textClass=/politik.*/", "textClass=/wirtschaft.*/"), (2002:2018))
diff --git a/man/geom_freq_by_year_ci.Rd b/man/geom_freq_by_year_ci.Rd
index ffdbdb3..74f8d40 100644
--- a/man/geom_freq_by_year_ci.Rd
+++ b/man/geom_freq_by_year_ci.Rd
@@ -2,12 +2,19 @@
% Please edit documentation in R/misc.R
\name{geom_freq_by_year_ci}
\alias{geom_freq_by_year_ci}
-\title{Plot frequency by year graphs with confidence intervals}
+\title{Experimental: Plot frequency by year graphs with confidence intervals}
\usage{
-geom_freq_by_year_ci()
+geom_freq_by_year_ci(mapping = aes(ymin = conf.low, ymax = conf.high),
+ ...)
+}
+\arguments{
+\item{mapping}{Set of aesthetic mappings created by aes() or aes_(). If specified and inherit.aes = TRUE (the default), it is combined with the default mapping at the top level of the plot. You must supply mapping if there is no plot mapping.}
+
+\item{...}{Other arguments passed to geom_ribbon, geom_line, and geom_click_point.}
}
\description{
-Convenience function for plotting typical frequency by year graphs with confidence intervals using ggplot2.
+Experimental convenience function for plotting typical frequency by year graphs with confidence intervals using ggplot2.
+\bold{Warning:} This function may be moved to a new package.
}
\examples{
library(ggplot2)
@@ -17,7 +24,7 @@
cbind(frequencyQuery(kco, "[tt/l=Heuschrecke]",
paste0(.$condition," & pubDate in ", .$year))) \%>\%
ipm() \%>\%
- ggplot(aes(year, ipm, fill = condition, color = condition, ymin = conf.low, ymax = conf.high)) +
+ ggplot(aes(year, ipm, fill = condition, color = condition)) +
geom_freq_by_year_ci()
}
diff --git a/man/ggplotly.Rd b/man/ggplotly.Rd
new file mode 100644
index 0000000..7aedff6
--- /dev/null
+++ b/man/ggplotly.Rd
@@ -0,0 +1,40 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/misc.R
+\name{ggplotly}
+\alias{ggplotly}
+\title{Experimental: Convert ggplot2 to plotly with hyperlinks to KorAP queries}
+\usage{
+ggplotly(p = ggplot2::last_plot(), tooltip = c("x", "y", "colour",
+ "url"), ...)
+}
+\arguments{
+\item{p}{a ggplot object.}
+
+\item{tooltip}{a character vector specifying which aesthetic mappings to show
+in the tooltip. If you want hyperlinks to KorAP queries you need to include
+\code{"url"} here.}
+
+\item{...}{Other arguments passed to \code{plotly::ggplotly}}
+}
+\description{
+\code{RKorAPClient::ggplotly} converts a \code{ggplot2::ggplot()} object to a plotly
+object with hyperlinks from data points to corresponding KorAP queries.
+\bold{Warning:} This function may be moved to a new package.
+}
+\examples{
+library(ggplot2)
+kco <- new("KorAPConnection", verbose=TRUE)
+g <- expand_grid(condition = c("textDomain = /Wirtschaft.*/", "textDomain != /Wirtschaft.*/"),
+ year = (2002:2018)) \%>\%
+ cbind(frequencyQuery(kco, "[tt/l=Heuschrecke]",
+ paste0(.$condition," & pubDate in ", .$year))) \%>\%
+ ipm() \%>\%
+ ggplot(aes(year, ipm, fill = condition, color = condition)) +
+## theme_light(base_size = 20) +
+ geom_freq_by_year_ci()
+p <- ggplotly(g)
+print(p)
+## saveWidget(p, paste0(tmpdir(), "heuschrecke.html")
+
+
+}