Skip to content

Commit b29162c

Browse files
committed
Address #141: Added plotly
1 parent 4ec2a6c commit b29162c

32 files changed

Lines changed: 301 additions & 58 deletions

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ Suggests:
2525
covr,
2626
knitr,
2727
jsonlite,
28-
nycflights13
28+
nycflights13,
29+
plotly
2930
SystemRequirements: pandoc (>= 1.12.3) - http://pandoc.org
3031
License: MIT + file LICENSE
3132
Language: en-US

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# DataExplorer 0.9.0
2+
## New Features
3+
* [#141](https://github.com/boxuancui/DataExplorer/issues/141): Added `plotly` argument to all plot functions. When `plotly = TRUE`, plots are converted to interactive plotly objects via `plotly::ggplotly()` (requires the plotly package).
4+
25
## Enhancements
36
* [#181](https://github.com/boxuancui/DataExplorer/issues/181): Added `by` argument to `plot_histogram` and `plot_density` to break down distributions by a discrete or continuous feature.
47

R/create_report.R

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#' @param output_file output file name in \link[rmarkdown]{render}. Default is "report.html".
77
#' @param output_dir output directory for report in \link[rmarkdown]{render}. Default is user's current directory.
88
#' @param y name of response variable if any. Response variables will be passed to appropriate plotting functions automatically.
9+
#' @param plotly if \code{TRUE}, use interactive plotly charts in the report (requires the \pkg{plotly} package). Default is \code{FALSE}. Only applies to HTML output; PDF reports use static plots.
910
#' @param config report configuration generated by \link{configure_report}.
1011
#' @param report_title report title. Default is "Data Profiling Report".
1112
#' @param \dots other arguments to be passed to \link[rmarkdown]{render}.
@@ -33,6 +34,13 @@
3334
#' # Create report
3435
#' create_report(iris)
3536
#' create_report(airquality, y = "Ozone")
37+
#'
38+
#' # Create report with plotly
39+
#' # Note: It is a known issue that some facet panels may not show up in plotly.
40+
#' # More details in the following issues:
41+
#' # * https://github.com/plotly/plotly.R/issues/1243
42+
#' # * https://github.com/plotly/plotly.R/issues/1962
43+
#' create_report(airquality, y = "Ozone", plotly = TRUE)
3644
#'
3745
#' # Load library
3846
#' library(ggplot2)
@@ -92,6 +100,7 @@ create_report <- function(data,
92100
output_file = "report.html",
93101
output_dir = getwd(),
94102
y = NULL,
103+
plotly = FALSE,
95104
config = configure_report(),
96105
report_title = "Data Profiling Report",
97106
...) {
@@ -117,7 +126,7 @@ create_report <- function(data,
117126
output_file = output_file,
118127
output_dir = output_dir,
119128
intermediates_dir = output_dir,
120-
params = list(data = data, report_config = config, response = y, set_title = report_title),
129+
params = list(data = data, report_config = config, response = y, set_title = report_title, plotly = plotly),
121130
...
122131
))
123132
## Open report (use path returned by render in case extension was normalized)

R/plot.R

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#' @param title plot title
66
#' @param ggtheme complete ggplot2 themes
77
#' @param theme_config a list of configurations to be passed to \link[ggplot2]{theme}
8+
#' @param plotly if \code{TRUE}, convert ggplot to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
89
#' @param \dots other arguments to be passed
910
#' @return invisibly return the named list of ggplot objects
1011
#' @keywords internal
@@ -26,7 +27,7 @@
2627
#' "aspect.ratio" = 1
2728
#' )
2829
#' )
29-
plotDataExplorer <- function(plot_obj, title, ggtheme, theme_config, ...) {
30+
plotDataExplorer <- function(plot_obj, title, ggtheme, theme_config, plotly = FALSE, ...) {
3031
UseMethod("plotDataExplorer")
3132
}
3233

@@ -48,20 +49,43 @@ plotDataExplorer <- function(plot_obj, title, ggtheme, theme_config, ...) {
4849
#' @import gridExtra
4950
#' @export
5051
#' @seealso \link{plotDataExplorer} \link{plotDataExplorer.single} \link{plotDataExplorer.multiple}
51-
plotDataExplorer.grid <- function(plot_obj, title, ggtheme, theme_config, page_layout, nrow, ncol, ...) {
52+
plotDataExplorer.grid <- function(plot_obj, title, ggtheme, theme_config, page_layout, nrow, ncol, plotly = FALSE, ...) {
5253
plot_list <- lapply(plot_obj, function(p) {
5354
p +
5455
eval(ggtheme) +
5556
do.call(theme, theme_config)
5657
})
5758

58-
if (length(page_layout) > 1) {
59-
invisible(lapply(names(page_layout), function(pg_name) {
60-
index <- page_layout[[pg_name]]
61-
suppressMessages(do.call(grid.arrange, c(plot_list[index], ncol = ncol, nrow = nrow, top = title, bottom = pg_name)))
62-
}))
59+
if (plotly) {
60+
if (!requireNamespace("plotly", quietly = TRUE)) {
61+
stop("Package \"plotly\" is required for plotly = TRUE. Install it with install.packages(\"plotly\").")
62+
}
63+
if (length(page_layout) > 1) {
64+
pl_list <- lapply(names(page_layout), function(pg_name) {
65+
index <- page_layout[[pg_name]]
66+
plist <- lapply(plot_list[index], function(p) suppressWarnings(plotly::ggplotly(p)))
67+
plotly::subplot(plist, nrows = nrow, ncols = ncol, margin = 0.05, titleY = TRUE, titleX = TRUE)
68+
})
69+
} else {
70+
plist <- lapply(plot_list, function(p) suppressWarnings(plotly::ggplotly(p)))
71+
pl_list <- list(plotly::subplot(plist, nrows = nrow, ncols = ncol, margin = 0.05, titleY = TRUE, titleX = TRUE))
72+
}
73+
if (isTRUE(getOption("knitr.in.progress"))) {
74+
if (requireNamespace("htmltools", quietly = TRUE)) {
75+
return(do.call(htmltools::tagList, pl_list))
76+
}
77+
return(pl_list)
78+
}
79+
invisible(lapply(pl_list, print))
6380
} else {
64-
suppressMessages(do.call(grid.arrange, c(plot_list, ncol = ncol, nrow = nrow, top = title)))
81+
if (length(page_layout) > 1) {
82+
invisible(lapply(names(page_layout), function(pg_name) {
83+
index <- page_layout[[pg_name]]
84+
suppressMessages(do.call(grid.arrange, c(plot_list[index], ncol = ncol, nrow = nrow, top = title, bottom = pg_name)))
85+
}))
86+
} else {
87+
suppressMessages(do.call(grid.arrange, c(plot_list, ncol = ncol, nrow = nrow, top = title)))
88+
}
6589
}
6690

6791
invisible(plot_list)
@@ -81,13 +105,22 @@ plotDataExplorer.grid <- function(plot_obj, title, ggtheme, theme_config, page_l
81105
#' @import ggplot2
82106
#' @export
83107
#' @seealso \link{plotDataExplorer} \link{plotDataExplorer.grid} \link{plotDataExplorer.multiple}
84-
plotDataExplorer.single <- function(plot_obj, title, ggtheme, theme_config, ...) {
108+
plotDataExplorer.single <- function(plot_obj, title, ggtheme, theme_config, plotly = FALSE, ...) {
85109
plot_obj <- plot_obj +
86110
ggtitle(title) +
87111
eval(ggtheme) +
88112
do.call(theme, theme_config)
89113

90-
print(plot_obj)
114+
if (plotly) {
115+
if (!requireNamespace("plotly", quietly = TRUE)) {
116+
stop("Package \"plotly\" is required for plotly = TRUE. Install it with install.packages(\"plotly\").")
117+
}
118+
pl <- suppressWarnings(plotly::ggplotly(plot_obj))
119+
if (isTRUE(getOption("knitr.in.progress"))) return(pl)
120+
print(pl)
121+
} else {
122+
print(plot_obj)
123+
}
91124
invisible(plot_obj)
92125
}
93126

@@ -108,7 +141,7 @@ plotDataExplorer.single <- function(plot_obj, title, ggtheme, theme_config, ...)
108141
#' @importFrom stats setNames
109142
#' @export
110143
#' @seealso \link{plotDataExplorer} \link{plotDataExplorer.grid} \link{plotDataExplorer.single}
111-
plotDataExplorer.multiple <- function(plot_obj, title, ggtheme, theme_config, page_layout, facet_wrap_args = list(), ...) {
144+
plotDataExplorer.multiple <- function(plot_obj, title, ggtheme, theme_config, page_layout, facet_wrap_args = list(), plotly = FALSE, ...) {
112145
n <- length(page_layout)
113146
plot_list <- lapply(setNames(seq.int(n), paste0("page_", seq.int(n))), function(i) {
114147
plot_obj[[i]] +
@@ -119,6 +152,21 @@ plotDataExplorer.multiple <- function(plot_obj, title, ggtheme, theme_config, pa
119152
do.call(theme, theme_config)
120153
})
121154

122-
invisible(capture.output(print(plot_list)))
155+
if (plotly) {
156+
if (!requireNamespace("plotly", quietly = TRUE)) {
157+
stop("Package \"plotly\" is required for plotly = TRUE. Install it with install.packages(\"plotly\").")
158+
}
159+
pl_list <- lapply(plot_list, function(p) suppressWarnings(plotly::ggplotly(p)))
160+
if (isTRUE(getOption("knitr.in.progress"))) {
161+
if (requireNamespace("htmltools", quietly = TRUE)) {
162+
return(do.call(htmltools::tagList, pl_list))
163+
}
164+
lapply(pl_list, print)
165+
return(invisible(plot_list))
166+
}
167+
invisible(lapply(pl_list, print))
168+
} else {
169+
invisible(capture.output(print(plot_list)))
170+
}
123171
invisible(plot_list)
124172
}

R/plot_bar.R

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#' @param nrow number of rows per page. Default is 3.
1515
#' @param ncol number of columns per page. Default is 3.
1616
#' @param parallel enable parallel? Default is \code{FALSE}.
17+
#' @param plotly if \code{TRUE}, convert to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
1718
#' @return invisibly return the named list of ggplot objects
1819
#' @keywords plot_bar
1920
#' @details If a discrete feature contains more categories than \code{maxcat} specifies, it will not be passed to the plotting function.
@@ -34,14 +35,17 @@
3435
#' # Plot bar charts by `cut`
3536
#' plot_bar(diamonds, by = "cut")
3637
#' plot_bar(diamonds, by = "cut", by_position = "dodge")
38+
#'
39+
#' # Interactive plotly version (requires the plotly package)
40+
#' # plot_bar(diamonds, plotly = TRUE)
3741

3842
plot_bar <- function(data, with = NULL,
3943
by = NULL, by_position = "fill",
4044
maxcat = 50, order_bar = TRUE, binary_as_factor = TRUE,
4145
title = NULL,
4246
ggtheme = theme_gray(), theme_config = list(),
4347
nrow = 3L, ncol = 3L,
44-
parallel = FALSE) {
48+
parallel = FALSE, plotly = FALSE) {
4549
## Declare variable first to pass R CMD check
4650
frequency <- measure <- variable <- value <- facet_value <- NULL
4751
## Check if input is data.table
@@ -120,6 +124,7 @@ plot_bar <- function(data, with = NULL,
120124
title = title,
121125
ggtheme = ggtheme,
122126
theme_config = theme_config,
127+
plotly = plotly,
123128
facet_wrap_args = list(
124129
"facet" = ~ variable,
125130
"nrow" = nrow,

R/plot_boxplot.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#' @param nrow number of rows per page
1414
#' @param ncol number of columns per page
1515
#' @param parallel enable parallel? Default is \code{FALSE}.
16+
#' @param plotly if \code{TRUE}, convert to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
1617
#' @return invisibly return the named list of ggplot objects
1718
#' @keywords plot_boxplot
1819
#' @import data.table
@@ -41,7 +42,7 @@ plot_boxplot <- function(data, by,
4142
title = NULL,
4243
ggtheme = theme_gray(), theme_config = list(),
4344
nrow = 3L, ncol = 4L,
44-
parallel = FALSE) {
45+
parallel = FALSE, plotly = FALSE) {
4546
## Declare variable first to pass R CMD check
4647
variable <- by_f <- value <- NULL
4748
## Check if input is data.table
@@ -85,6 +86,7 @@ plot_boxplot <- function(data, by,
8586
title = title,
8687
ggtheme = ggtheme,
8788
theme_config = theme_config,
89+
plotly = plotly,
8890
facet_wrap_args = list(
8991
"facet" = ~ variable,
9092
"nrow" = nrow,

R/plot_correlation.R

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#' @param title plot title
1010
#' @param ggtheme complete ggplot2 themes. The default is \link[ggplot2]{theme_gray}.
1111
#' @param theme_config a list of configurations to be passed to \link[ggplot2]{theme}.
12+
#' @param plotly if \code{TRUE}, convert to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
1213
#' @return invisibly return the ggplot object
1314
#' @keywords plot_correlation
1415
#' @details For discrete features, the function first dummifies all categories, then calculates the correlation matrix (see \link[stats]{cor}) and plots it.
@@ -27,7 +28,8 @@ plot_correlation <- function(data, type = c("all", "discrete", "continuous"), ma
2728
title = NULL,
2829
ggtheme = theme_gray(),
2930
theme_config = list("legend.position" = "bottom",
30-
"axis.text.x" = element_text(angle = 90))) {
31+
"axis.text.x" = element_text(angle = 90)),
32+
plotly = FALSE) {
3133
## Declare variable first to pass R CMD check
3234
Var1 <- Var2 <- value <- NULL
3335
## Set data to data.table
@@ -73,6 +75,7 @@ plot_correlation <- function(data, type = c("all", "discrete", "continuous"), ma
7375
plot_obj = output,
7476
title = title,
7577
ggtheme = ggtheme,
76-
theme_config = theme_config
78+
theme_config = theme_config,
79+
plotly = plotly
7780
)
7881
}

R/plot_density.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#' @param nrow number of rows per page. Default is 4.
1313
#' @param ncol number of columns per page. Default is 4.
1414
#' @param parallel enable parallel? Default is \code{FALSE}.
15+
#' @param plotly if \code{TRUE}, convert to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
1516
#' @return invisibly return the named list of ggplot objects
1617
#' @keywords plot_density
1718
#' @import data.table
@@ -40,7 +41,7 @@ plot_density <- function(data, by = NULL, binary_as_factor = TRUE,
4041
title = NULL,
4142
ggtheme = theme_gray(), theme_config = list(),
4243
nrow = 4L, ncol = 4L,
43-
parallel = FALSE) {
44+
parallel = FALSE, plotly = FALSE) {
4445
## Declare variable first to pass R CMD check
4546
variable <- value <- by_f <- NULL
4647
## Check if input is data.table
@@ -95,6 +96,7 @@ plot_density <- function(data, by = NULL, binary_as_factor = TRUE,
9596
title = title,
9697
ggtheme = ggtheme,
9798
theme_config = theme_config,
99+
plotly = plotly,
98100
facet_wrap_args = list(
99101
"facet" = ~ variable,
100102
"nrow" = nrow,

R/plot_histogram.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#' @param nrow number of rows per page. Default is 4.
1313
#' @param ncol number of columns per page. Default is 4.
1414
#' @param parallel enable parallel? Default is \code{FALSE}.
15+
#' @param plotly if \code{TRUE}, convert to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
1516
#' @return invisibly return the named list of ggplot objects
1617
#' @keywords plot_histogram
1718
#' @import data.table
@@ -37,7 +38,7 @@ plot_histogram <- function(data, by = NULL, binary_as_factor = TRUE,
3738
title = NULL,
3839
ggtheme = theme_gray(), theme_config = list(),
3940
nrow = 4L, ncol = 4L,
40-
parallel = FALSE) {
41+
parallel = FALSE, plotly = FALSE) {
4142
## Declare variable first to pass R CMD check
4243
variable <- value <- by_f <- NULL
4344
## Check if input is data.table
@@ -92,6 +93,7 @@ plot_histogram <- function(data, by = NULL, binary_as_factor = TRUE,
9293
title = title,
9394
ggtheme = ggtheme,
9495
theme_config = theme_config,
96+
plotly = plotly,
9597
facet_wrap_args = list(
9698
"facet" = ~ variable,
9799
"nrow" = nrow,

R/plot_intro.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#' @param title plot title
77
#' @param ggtheme complete ggplot2 themes. The default is \link[ggplot2]{theme_gray}.
88
#' @param theme_config a list of configurations to be passed to \link[ggplot2]{theme}.
9+
#' @param plotly if \code{TRUE}, convert to interactive plotly object (requires the \pkg{plotly} package). Default is \code{FALSE}.
910
#' @return invisibly return the ggplot object
1011
#' @keywords plot_intro
1112
#' @import ggplot2
@@ -17,7 +18,7 @@
1718
#' plot_intro(airquality)
1819
#' plot_intro(iris)
1920

20-
plot_intro <- function(data, geom_label_args = list(), title = NULL, ggtheme = theme_gray(), theme_config = list()) {
21+
plot_intro <- function(data, geom_label_args = list(), title = NULL, ggtheme = theme_gray(), theme_config = list(), plotly = FALSE) {
2122
## Declare variable first to pass R CMD check
2223
id <- dimension <- variable <- value <- NULL
2324
## Get intro data
@@ -54,6 +55,7 @@ plot_intro <- function(data, geom_label_args = list(), title = NULL, ggtheme = t
5455
plot_obj = output,
5556
title = ifelse(is.null(title), paste("Memory Usage:", memory_usage_string), title),
5657
ggtheme = ggtheme,
57-
theme_config = theme_config
58+
theme_config = theme_config,
59+
plotly = plotly
5860
)
5961
}

0 commit comments

Comments
 (0)