The goal of tidyview is to provide an extensible replacement for utils::View()
.
You can install the released version of tidyview from CRAN with:
install.packages("tidyview")
By default, view()
forwards to utils::View()
. This isn't useful for rendering an rmarkdown document, so the first code shown here will be how to turn it off.
library(tidyview)
suppress_view()
Now we're safe to use view()
:
library(tidyverse)
#> ── Attaching packages ─────────────────────────────────────────────────── tidyverse 1.2.1 ──
#> ✔ ggplot2 2.2.1 ✔ purrr 0.2.5
#> ✔ tibble 1.4.2.9002 ✔ dplyr 0.7.6
#> ✔ tidyr 0.8.1 ✔ stringr 1.3.1
#> ✔ readr 1.1.1 ✔ forcats 0.3.0
#> ── Conflicts ────────────────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag() masks stats::lag()
view(mtcars)
#> Suppressed viewing of mtcars
mtcars %>%
view() %>%
nrow()
#> Suppressed viewing of .
#> [1] 32
Note the pipe-friendlyness -- the input is passed through, invisibly, and can be processed later on. In an interactive session, the code above would have opened two data viewers, via the default_view_handler()
function:
default_view_handler
#> function(x, title) {
#> View <- get("View", envir = as.environment("package:utils"))
#> View(x, title)
#> }
#> <bytecode: 0x56424bdec790>
#> <environment: namespace:tidyview>
Custom view handlers can be made available through factories. The factory is a design pattern, see the Wikipedia article if you're not familiar with it.
-
A factory is registered via
register_view_handler_factory()
. -
Each time
view()
is called, all registered factories are consulted. -
The first factory that returns a valid handler, i.e. a function similar to the
default_view_handler()
seen above, wins. The handler is called with the object. -
If no factory takes responsibility, the default view handler is used.
The factory must be a pure function without (user-visible) side effects!
We register a view handler factory that outputs the title and the dimensions of the object for 2D objects, and does nothing for all other objects.
my_view_handler_factory <- function(x) {
if (length(dim(x)) != 2) return (NULL)
my_view_handler
}
my_view_handler <- function(x, title) {
cat("Title: ", title, "\n", sep = "")
cat("Dimensions: ", paste(dim(x), collapse = " x "), "\n", sep = "")
}
register_view_handler_factory(my_view_handler_factory)
Now, when we view()
a data frame, we get console output:
view(mtcars)
#> Title: mtcars
#> Dimensions: 32 x 11
mtcars %>%
view() %>%
nrow()
#> Title: .
#> Dimensions: 32 x 11
#> [1] 32
mtcars %>%
view("my title")
#> Title: my title
#> Dimensions: 32 x 11
(The dot .
in the title is created by the pipe. If you need to distinguish views in a pipe-based workflow, use the title
argument to view()
.)
Viewing a vector still doesn't do anything, this is how we designed our view handler factory:
view(1:10)
#> Suppressed viewing of 1:10
The implementation of suppress_view()
shouldn't be surprising:
suppress_view
#> function() {
#> register_view_handler_factory(void_view_handler_factory)
#> }
#> <bytecode: 0x56424a2c1020>
#> <environment: namespace:tidyview>
Factories are consulted in reverse registration order, calling suppress_view()
again moves the void handler factory to the top.
suppress_view()
view(mtcars)
#> Suppressed viewing of mtcars