TODO: - Document add_meta_tags() - Document default
write_panels(..., force = FALSE)
This repository contains an rewrite of the trelliscopejs R package, now simply called trelliscope.
You can install the development version of trelliscope from GitHub with:
# install.packages("devtools")
# load_all()
devtools::install_github("trelliscope/trelliscope")Trelliscope provides a simple mechanism to make a collection of visualizations and display them as interactive small multiples. This is a useful general visualization technique for many scenarios, particularly when looking at a somewhat large dataset comprised of many natural subsets.
The Trelliscope R package provides utilities to create the visualizations, specify metadata about the visualizations that can be used to interactively navigate them, and specify other aspects of how the visualization viewer should behave. These specifications are given to a Trelliscope viewer written in JavaScript.
The basic principle behind the design of the R package is that you specify a collection of visualizations as a data frame, with one column representing the plot (either as a plot object such as ggplot or as a reference to an image such as a png, svg, or even html file), and the other columns representing metadata about each visualization.
This package provides utilities to help build these data frames and then explore them in an interactive viewer.
As a simple example, let’s consider the gapminder dataset that comes
with the gapminder package.
# install.packages("gapminder")
library(gapminder)
gapminder
#> # A tibble: 1,704 × 6
#> country continent year lifeExp pop gdpPercap
#> <fct> <fct> <int> <dbl> <int> <dbl>
#> 1 Afghanistan Asia 1952 28.8 8425333 779.
#> 2 Afghanistan Asia 1957 30.3 9240934 821.
#> 3 Afghanistan Asia 1962 32.0 10267083 853.
#> 4 Afghanistan Asia 1967 34.0 11537966 836.
#> 5 Afghanistan Asia 1972 36.1 13079460 740.
#> 6 Afghanistan Asia 1977 38.4 14880372 786.
#> 7 Afghanistan Asia 1982 39.9 12881816 978.
#> 8 Afghanistan Asia 1987 40.8 13867957 852.
#> 9 Afghanistan Asia 1992 41.7 16317921 649.
#> 10 Afghanistan Asia 1997 41.8 22227415 635.
#> # … with 1,694 more rowsThis data provides statistics such as life expectancy annually for 142 countries.
Suppose we want to visualize life expectancy vs. year for each country. One way to do this is to create a data frame with one row per country, with one of the columns of the data frame containing a plot.
library(trelliscope)
suppressPackageStartupMessages(
library(tidyverse, warn.conflicts = FALSE) # for ggplot2, tidyr, dplyr, purrr
)
visdf <- gapminder %>%
tidyr::nest(data = !dplyr::one_of(c("continent", "country"))) %>%
dplyr::mutate(
mean_lifeexp = purrr::map_dbl(data, ~ mean(.x$lifeExp)),
panel = trelliscope::map_plot(data,
~ (ggplot2::ggplot(ggplot2::aes(year, lifeExp), data = .x)) +
ggplot2::geom_point())
)
visdf
#> # A tibble: 142 × 5
#> country continent data mean_lifeexp panel
#> <fct> <fct> <list> <dbl> <nstd_pnl>
#> 1 Afghanistan Asia <tibble [12 × 4]> 37.5 <gg>
#> 2 Albania Europe <tibble [12 × 4]> 68.4 <gg>
#> 3 Algeria Africa <tibble [12 × 4]> 59.0 <gg>
#> 4 Angola Africa <tibble [12 × 4]> 37.9 <gg>
#> 5 Argentina Americas <tibble [12 × 4]> 69.1 <gg>
#> 6 Australia Oceania <tibble [12 × 4]> 74.7 <gg>
#> 7 Austria Europe <tibble [12 × 4]> 73.1 <gg>
#> 8 Bahrain Asia <tibble [12 × 4]> 65.6 <gg>
#> 9 Bangladesh Asia <tibble [12 × 4]> 49.8 <gg>
#> 10 Belgium Europe <tibble [12 × 4]> 73.6 <gg>
#> # … with 132 more rowsHere we have built a data frame of visualizations, the basic construct
that is needed to create a Trelliscope display. We have a data frame
with 142 rows, one for each country. We have country metadata such as
the country and continent names, as well as the mean life expectency,
and then we have a column “panel” that contains a plot for each country
of life expectancy vs. year. (Note: We show the package:: prefixes for
each function used in this example to highlight what packages are being
used but will remove these from future examples).
There is a lot going on in the code example above that should be familiar if you have experience with Tidyverse packages such as dplyr and tidyr. A great resource for this can be found in “R for Data Science”, particularly this chapter which mimics many of the ideas here of nesting and list columns with the same dataset.
The one non-tidyverse function used in this example is map_plot().
This acts as an analog to map functions in the purrr package such as
map_dbl(), etc., that applies a function to every element in a list
and returns a list-column that indicates that it contains plots that can
be used in a Trelliscope display.
Note that although the tidyverse provides many helpful functions, it
does not matter what package or approach you use as long as you can get
your data into the form of a data frame with one row per visualization
and a visualiztion column created with map_plot().
Once you have data in this form, you can create a Trelliscope display by simply doing the following:
as_trelliscope_df(visdf, name = "life expectancy") %>% write_trelliscope()Passing the data frame to as_trelliscope_df() creates a trelliscope
data frame that provides information about the display that will be
created from the data frame, such the name of the display and an
optional description and tags, as well as the directory where the dispay
will be written (if not specified it is placed in a temporary
directory). Then write_trelliscope() writes out and shows the display
using the Trelliscope JavaScript viewer app.
[screenshot (TODO)]
Now from the app you can interatively view all 142 of the visualizations, with controls to specify what order they should appear in, how many to view at once, and filter to only visualizations of interest (e.g. countries in Africa with an average life expectancy of less than 50 years).
From this you can see how it can be useful to provide as much metadata about each visualization as might be useful for a meaningful interactive experience, especially when the number of visualizations is much larger. For example, we could add metrics for the latest life expectancy, the slope of the trend of life expectancy over time, the country’s population, etc. that could help us navigate to interesting visualizations in the display.
There are many functions provided that operate on the object that comes
out of as_trelliscope_df() that allow us to specify more information
about the display and its behavior before we write it out with
write_trelliscope(). We will discuss several of these later.
A utility function, facet_panels() makes it easier to achieve the same
result as what we showed in the previous example staying strictly within
ggplot and not needing to rely on the other tidyverse functions to nest
the data, etc.
The facet_panels() function works in a very similar manner as
ggplot2’s facet_wrap(), in that we are specifying that we want the
same visualization specification to be applied to each facet of the data
that we specify.
For example, using ggplot2, we might do the following to visualize each country separately:
ggplot(aes(year, lifeExp), data = gapminder) +
geom_point() +
facet_wrap(~ continent + country)This will plot life expectancy vs. year for each of the 142 countries and lay the plots out in a page.
With Trelliscope, we can swap out facet_wrap() with facet_panels():
p <- ggplot(aes(year, lifeExp), data = gapminder) +
geom_point() +
facet_panels(~ continent + country)This creates a ggplot object that we can turn into a data frame suitable for Trelliscope with the following:
visdf <- nest_panels(p)
visdf
#> # A tibble: 142 × 4
#> country continent data panel
#> <fct> <fct> <list> <nstd_pnl>
#> 1 Afghanistan Asia <tibble [12 × 5]> <gg>
#> 2 Albania Europe <tibble [12 × 5]> <gg>
#> 3 Algeria Africa <tibble [12 × 5]> <gg>
#> 4 Angola Africa <tibble [12 × 5]> <gg>
#> 5 Argentina Americas <tibble [12 × 5]> <gg>
#> 6 Australia Oceania <tibble [12 × 5]> <gg>
#> 7 Austria Europe <tibble [12 × 5]> <gg>
#> 8 Bahrain Asia <tibble [12 × 5]> <gg>
#> 9 Bangladesh Asia <tibble [12 × 5]> <gg>
#> 10 Belgium Europe <tibble [12 × 5]> <gg>
#> # … with 132 more rowsThis builds a data frame similar to what we produced in the first
example, which we can modify in any way we would like to add more
per-country metadata (e.g. calculate mean life expectancy, merge other
demographic statistics, etc.) and then pass this to
as_trelliscope_df() to create our data frame of visualizations. Note
that we can pass p directly to as_trelliscope_df() as well in which
case it will build the panels for us, but it can be useful to have more
control over additional modifications to the data frame and the panel
building.
The nest_panels() function has a few arguments that allow us to
specify more about how we want the panels built. One is as_plotly
which we can set to TRUE to have the plots converted to interactive
plotly plots:
visdf <- nest_panels(p, as_plotly = TRUE)
visdf
#> # A tibble: 142 × 4
#> country continent data panel
#> <fct> <fct> <list> <nstd_pnl>
#> 1 Afghanistan Asia <tibble [12 × 5]> <plotly>
#> 2 Albania Europe <tibble [12 × 5]> <plotly>
#> 3 Algeria Africa <tibble [12 × 5]> <plotly>
#> 4 Angola Africa <tibble [12 × 5]> <plotly>
#> 5 Argentina Americas <tibble [12 × 5]> <plotly>
#> 6 Australia Oceania <tibble [12 × 5]> <plotly>
#> 7 Austria Europe <tibble [12 × 5]> <plotly>
#> 8 Bahrain Asia <tibble [12 × 5]> <plotly>
#> 9 Bangladesh Asia <tibble [12 × 5]> <plotly>
#> 10 Belgium Europe <tibble [12 × 5]> <plotly>
#> # … with 132 more rowsIf you are plotting with ggplot2, there are several benefits to using
facet_panels(). First, it fits more naturally into the ggplot2
paradigm, where you can build a Trelliscope visualization exactly as you
would with building a ggplot2 visualization. Second, you can make use of
the scales argument in facet_panels() (which behaves similarly to
the same argument in facet_wrap()) to ensure that the x and y axis
ranges of your plots behave the way you want. The default is for all
plots to have the same "fixed" axis ranges. This is an important
consideration in visualizing small multiples because if you are making
visual comparisons you often want to be comparing things on the same
scale. In the first example where we didn’t use facet_trellicope(), we
would have had to manually figure out the ranges of the x and y axes and
hard code them into our plots.
So far we have seen the following general set of steps to create a trelliscope display:
Starting with a data frame of raw data, df, we can create a data frame
of visualizations using tidyverse functions:
df %>%
nest(...) %>%
mutate(
panel = map_plot(...),
...
) %>%
as_trelliscope_df(...) %>%
write_trelliscope(...)or using facet_panels():
df %>%
(ggplot(...) + ... + facet_panels()) %>%
nest_panels() %>%
as_trelliscope_df() %>%
write_trelliscope()In between as_trelliscope_df() %>% write_trelliscope(), there are many
functions we can call that give us better control over how our display
looks and behaves. These include the following:
write_panels(): allows finer control over how panels are written (e.g. plot dimensions, file format, etc.)add_meta_defs(): specify metadata variable definitions (e.g. plain text variable descriptions, types, tags)add_meta_labels(): as an alternative to fully specifying metadata variable definitions, this is a convenience function to only supply labels for all of the variablesset_default_labels(),set_default_layout(),set_default_sort(),set_default_filters(): specify the initial state of the displayadd_view(): add any number of pre-defined “views” that navigate the user to specified states of the displayadd_inputs(): specify inputs that can collect user feedback for each panel in the display
Each of these functions takes a trelliscope data frame (created with
as_trelliscope_df()) and returns a modified trelliscope data frame,
making them suitable for chaining.
To illustrate some of these, let’s create a trelliscope data frame:
x <- (ggplot(aes(year, lifeExp), data = gapminder) +
geom_point() +
facet_panels(~ continent + country)) %>%
nest_panels() %>%
mutate(
mean_lifeexp = purrr::map_dbl(data, ~ mean(.x$lifeExp)),
min_lifeexp = purrr::map_dbl(data, ~ min(.x$lifeExp)),
mean_gdp = purrr::map_dbl(data, ~ mean(.x$gdpPercap)),
wiki_link = paste0("https://en.wikipedia.org/wiki/", country)
) %>%
as_trelliscope_df(name = "life expectancy")
x
#> ℹ Trelliscope data frame. Call show_info() for more information
#> # A tibble: 142 × 8
#> country continent data panel mean_…¹ min_l…² mean_…³ wiki_…⁴
#> <fct> <fct> <list> <nst> <dbl> <dbl> <dbl> <chr>
#> 1 Afghanistan Asia <tibble [12 × 5]> <gg> 37.5 28.8 803. https:…
#> 2 Albania Europe <tibble [12 × 5]> <gg> 68.4 55.2 3255. https:…
#> 3 Algeria Africa <tibble [12 × 5]> <gg> 59.0 43.1 4426. https:…
#> 4 Angola Africa <tibble [12 × 5]> <gg> 37.9 30.0 3607. https:…
#> 5 Argentina Americas <tibble [12 × 5]> <gg> 69.1 62.5 8956. https:…
#> 6 Australia Oceania <tibble [12 × 5]> <gg> 74.7 69.1 19981. https:…
#> 7 Austria Europe <tibble [12 × 5]> <gg> 73.1 66.8 20412. https:…
#> 8 Bahrain Asia <tibble [12 × 5]> <gg> 65.6 50.9 18078. https:…
#> 9 Bangladesh Asia <tibble [12 × 5]> <gg> 49.8 37.5 818. https:…
#> 10 Belgium Europe <tibble [12 × 5]> <gg> 73.6 68 19901. https:…
#> # … with 132 more rows, and abbreviated variable names ¹mean_lifeexp,
#> # ²min_lifeexp, ³mean_gdp, ⁴wiki_linkAs you can see, x is still a data frame. To see more information about
trelliscope-specific settings, you can use show_info():
show_info(x)
#> A trelliscope display
#> • Name: "life expectancy"
#> • Description: "life expectancy"
#> • Tags: none
#> • Key columns: "continent" and "country"
#> • Path:
#> "/var/folders/7b/thg__1xx7w98wc4rs8t3djrw0000gn/T//RtmpIdyzPk/file17b1a51b472aa"
#> • Number of panels: 142
#> • Panels written: no
#> • Metadata variables that will be inferred:
#> ───────────────────────────────────
#> name `inferred type` label
#> ───────────────────────────────────
#> country factor [none]
#> continent factor [none]
#> mean_lifeexp number [none]
#> min_lifeexp number [none]
#> mean_gdp number [none]
#> wiki_link string [none]
#> ───────────────────────────────────
#> • Variables that will be ignored as metadata: "data" and "panel"Each metadata variable can have addtional attributes specified about it
that enhance the user’s experience when viewing the display. The main
attribute is the metadata variable label. Without supplying a label,
variables will appear in the viewer by their variable names
(e.g. mean_gdp vs. a label such as
Mean of yearly GDP per capita (US$, inflation-adjusted)).
Additionally, we can specify the variable type, specify tags (e.g. “demographics”, “geography”, etc.) that can make variables easier to navigate in the viewer when there are many of them, and other type-specific parameters.
Each metadata variable can be specified by using a helper function that
specifies its type. Each of these has the arguments varname, label,
and tags (denoted below with ...) and any additional arguments which
are eitehr self-explanatory or can be further studied by looking at the
function help files.
meta_string(...): indicates the variable is a stringmeta_factor(..., levels): indicates the variable is a fator - the difference between this and a string is that the providedlevelsare used to determine the sorting order, etc. as opposed to alphabetically with stringsmeta_number(..., digits, locale): indicates a numeric variablemeta_currency(..., code): indicates a currency variable - essentially the same as a number but will be displayed differently in the appmeta_date(...): indicates a date variablemeta_datetime(...): indicates a datetime variablemeta_href(...): indicates a variable that contains a hyperlink to another web source - it will be rendered as a hyperlinkmeta_geo(..., latvar, longvar): indicates geographic coordinates (currently not supported)meta_graph(..., idvarname, direction): indicates network graph relationships between variables (currently not supported)
We can provide these specifications by calling add_meta_defs() on our
trelliscope data frame. This function takes as arguments any number of
meta_*() function calls. For example, let’s build up our object to
include some of these metadata variable specifications:
x <- x %>%
add_meta_defs(
meta_number("mean_gdp",
label = "Mean of annual GDP per capita (US$, inflation-adjusted)",
digits = 2),
meta_href("wiki_link", label = "Wikipedia country page")
)
x
#> ℹ Trelliscope data frame. Call show_info() for more information
#> # A tibble: 142 × 8
#> country continent data panel mean_…¹ min_l…² mean_…³ wiki_…⁴
#> <fct> <fct> <list> <nst> <dbl> <dbl> <dbl> <chr>
#> 1 Afghanistan Asia <tibble [12 × 5]> <gg> 37.5 28.8 803. https:…
#> 2 Albania Europe <tibble [12 × 5]> <gg> 68.4 55.2 3255. https:…
#> 3 Algeria Africa <tibble [12 × 5]> <gg> 59.0 43.1 4426. https:…
#> 4 Angola Africa <tibble [12 × 5]> <gg> 37.9 30.0 3607. https:…
#> 5 Argentina Americas <tibble [12 × 5]> <gg> 69.1 62.5 8956. https:…
#> 6 Australia Oceania <tibble [12 × 5]> <gg> 74.7 69.1 19981. https:…
#> 7 Austria Europe <tibble [12 × 5]> <gg> 73.1 66.8 20412. https:…
#> 8 Bahrain Asia <tibble [12 × 5]> <gg> 65.6 50.9 18078. https:…
#> 9 Bangladesh Asia <tibble [12 × 5]> <gg> 49.8 37.5 818. https:…
#> 10 Belgium Europe <tibble [12 × 5]> <gg> 73.6 68 19901. https:…
#> # … with 132 more rows, and abbreviated variable names ¹mean_lifeexp,
#> # ²min_lifeexp, ³mean_gdp, ⁴wiki_linkIf metadata variable definitions are not provided (such as here where we
don’t provide explicit definitions for country, continent,
min_lifeexp, and mean_lifeexp), they are inferred at the time the
display is written. The inference usually works pretty well but it
cannot infer labels and is not able to detect things like currencies.
Often the metadata inference works well enough that we might just want
to provide labels for our metadata variables and skip the more formal
metadata variable definition. We can do this with add_meta_labels().
This function simply takes a named set of parameters as input, with the
names indicating the variable name and the values indicating the labels.
For example:
x <- x %>%
add_meta_labels(
mean_lifeexp = "Mean of annual life expectancies",
min_lifeexp = "Lowest observed annual life expectancy"
)
x
#> ℹ Trelliscope data frame. Call show_info() for more information
#> # A tibble: 142 × 8
#> country continent data panel mean_…¹ min_l…² mean_…³ wiki_…⁴
#> <fct> <fct> <list> <nst> <dbl> <dbl> <dbl> <chr>
#> 1 Afghanistan Asia <tibble [12 × 5]> <gg> 37.5 28.8 803. https:…
#> 2 Albania Europe <tibble [12 × 5]> <gg> 68.4 55.2 3255. https:…
#> 3 Algeria Africa <tibble [12 × 5]> <gg> 59.0 43.1 4426. https:…
#> 4 Angola Africa <tibble [12 × 5]> <gg> 37.9 30.0 3607. https:…
#> 5 Argentina Americas <tibble [12 × 5]> <gg> 69.1 62.5 8956. https:…
#> 6 Australia Oceania <tibble [12 × 5]> <gg> 74.7 69.1 19981. https:…
#> 7 Austria Europe <tibble [12 × 5]> <gg> 73.1 66.8 20412. https:…
#> 8 Bahrain Asia <tibble [12 × 5]> <gg> 65.6 50.9 18078. https:…
#> 9 Bangladesh Asia <tibble [12 × 5]> <gg> 49.8 37.5 818. https:…
#> 10 Belgium Europe <tibble [12 × 5]> <gg> 73.6 68 19901. https:…
#> # … with 132 more rows, and abbreviated variable names ¹mean_lifeexp,
#> # ²min_lifeexp, ³mean_gdp, ⁴wiki_linkWe still haven’t specified labels for country and continent. If
labels are not provided, they will be set to the variable name. In the
case of these two varibles, the variable name is clear enough to not
need to specify the labels.
By default, the “key columns” will be shown as labels. If we’d like to
change what labels are shown when the display is opened, we can use
set_default_labels(), e.g.:
x <- x %>%
set_default_labels(c("country", "continent", "wiki_link"))We can also set the default panel layout:
x <- x %>%
set_default_layout(nrow = 3, ncol = 5)We can set the default sort order with set_default_sort():
x <- x %>%
set_default_sort(c("continent", "mean_lifeexp"), dir = c("asc", "desc"))We can set the default filter state with set_default_filters().
Currently there are two different kinds of filters:
filter_range(varname, min = ..., max = ...): works with numeric, date, or datetime variablesfilter_string(varname, values = ...): works with factor or string variables
x <- x %>%
set_default_filters(
filter_string("continent", values = "Africa"),
filter_range("mean_lifeexp", max = 50)
)More types of filters are planned.
Views are predefined sets of state that are made available in the viewer
to help the user get to regions of the display that are interesting in
different ways. You can add a view chaining the display through the
add_view() function.
add_view() takes a name as its first argument, and then any number
of state specifications. The functions available to set the state are
the following:
state_layout()state_labels()state_sort()filter_string()filter_range()
The state_*() functions have the same parameters as and behave
similarly to their set_*() counterparts except that unlike those,
these do not recieve a trelliscope data frame and return a trelliscope
data frame, but instead just specify a state. The filter_*() functions
we have seen already.
For example, suppose we wish to add a view that only shows countries with minimum life expectancy greater than or equal to 60, sorted from highest to lowest minimum life expectancy:
x <- x %>%
add_view(
name = "Countries with high life expectancy (min >= 60)",
filter_range("min_lifeexp", min = 60),
state_sort("min_lifeexp", dir = "desc")
)You can add as many views as you would like by chaining more calls to
add_view().
You can add user inputs that are attached to each panel of the display
using the add_inputs() function. This function takes any number of
arguments created by any of the following functions:
input_radio(name, label, options)input_checkbox(name, label, options)input_select(name, label, options)input_multiselect(name, label, options)input_text(name, label, width, height)input_number(name, label)
These specify different input types.
For example, if we want a free text input for comments as well as yes/no question asking if the data looks correct for the panel, we can do the following:
x <- x %>%
add_inputs(
input_text(name = "comments", label = "Comments about this panel",
width = 100, height = 6),
input_radio(name = "looks_correct",
label = "Does the data look correct?", options = c("no", "yes"))
) %>%
add_input_email("johndoe123@fakemail.net")Let’s see how all of these operations are reflected in our trelliscope data frame:
show_info(x)
#> A trelliscope display
#> • Name: "life expectancy"
#> • Description: "life expectancy"
#> • Tags: none
#> • Key columns: "continent" and "country"
#> • Path:
#> "/var/folders/7b/thg__1xx7w98wc4rs8t3djrw0000gn/T//RtmpIdyzPk/file17b1a51b472aa"
#> • Number of panels: 142
#> • Panels written: no
#> • Defined metadata variables:
#> ─────────────────────────────────────────────────
#> name type label tags
#> ─────────────────────────────────────────────────
#> mean_gdp number Mean of annual GDP per ca… []
#> wiki_link href Wikipedia country page []
#> ─────────────────────────────────────────────────
#> • Metadata variables that will be inferred:
#> ───────────────────────────────────────────────────────────────────
#> name `inferred type` label
#> ───────────────────────────────────────────────────────────────────
#> country factor [none]
#> continent factor [none]
#> mean_lifeexp number Mean of annual life expectancies
#> min_lifeexp number Lowest observed annual life expectancy
#> ───────────────────────────────────────────────────────────────────
#> • Variables that will be ignored as metadata: "data" and "panel"Now that we have built up our trelliscope data frame, we can write it
out as specified before with write_trelliscope().
write_trelliscope(x)
#> Writing panels ■ 1% | ETA: 2m
#> Writing panels ■■■■■ 15% | ETA: 18s
#> Writing panels ■■■■■■■■■■■■■■■ 46% | ETA: 7s
#> Writing panels ■■■■■■■■■■■■■■■■■■■■■■■■ 77% | ETA: 3s
#> Writing panels ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 100% | ETA: 0s
#> ℹ Meta definitions inferred for variables "country", "continent",
#> "mean_lifeexp", and "min_lifeexp"
#> ℹ No default "layout" state supplied for view 'Countries with high life
#> expectancy (min >= 60)'. Using nrow=2, ncol=3.
#> ℹ No default "labels" state supplied for view 'Countries with high life
#> expectancy (min >= 60)'. Using continent, country.
#> ℹ Trelliscope written to
#> /var/folders/7b/thg__1xx7w98wc4rs8t3djrw0000gn/T//RtmpIdyzPk/file17b1a51b472aa/index.html
#> Open this file or call view_trelliscope() to view.list.files(disp$path)
This writes the panels if they haven’t been written yet, and then writes out a JSON representation of all of the other specifications we have made for the app to consume.
To see what the JSON representation of this looks like for the display we have been building:
x %>% as_json()
#> ℹ Meta definitions inferred for variables "country", "continent",
#> "mean_lifeexp", and "min_lifeexp"
#> ℹ No default "layout" state supplied for view 'Countries with high life
#> expectancy (min >= 60)'. Using nrow=2, ncol=3.
#> ℹ No default "labels" state supplied for view 'Countries with high life
#> expectancy (min >= 60)'. Using continent, country.
#> {
#> "name": "life expectancy",
#> "description": "life expectancy",
#> "tags": [],
#> "keycols": ["continent", "country"],
#> "keysig": null,
#> "metas": [
#> {
#> "locale": true,
#> "digits": 2,
#> "sortable": true,
#> "filterable": true,
#> "tags": [],
#> "label": "Mean of annual GDP per capita (US$, inflation-adjusted)",
#> "type": "number",
#> "varname": "mean_gdp"
#> },
#> {
#> "sortable": false,
#> "filterable": false,
#> "tags": [],
#> "label": "Wikipedia country page",
#> "type": "href",
#> "varname": "wiki_link"
#> },
#> {
#> "levels": ["Afghanistan", "Albania", "Algeria", "Angola", "Argentina", "Australia", "Austria", "Bahrain", "Bangladesh", "Belgium", "Benin", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo, Dem. Rep.", "Congo, Rep.", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba", "Czech Republic", "Denmark", "Djibouti", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Ethiopia", "Finland", "France", "Gabon", "Gambia", "Germany", "Ghana", "Greece", "Guatemala", "Guinea", "Guinea-Bissau", "Haiti", "Honduras", "Hong Kong, China", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kenya", "Korea, Dem. Rep.", "Korea, Rep.", "Kuwait", "Lebanon", "Lesotho", "Liberia", "Libya", "Madagascar", "Malawi", "Malaysia", "Mali", "Mauritania", "Mauritius", "Mexico", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway", "Oman", "Pakistan", "Panama", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Puerto Rico", "Reunion", "Romania", "Rwanda", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Sierra Leone", "Singapore", "Slovak Republic", "Slovenia", "Somalia", "South Africa", "Spain", "Sri Lanka", "Sudan", "Swaziland", "Sweden", "Switzerland", "Syria", "Taiwan", "Tanzania", "Thailand", "Togo", "Trinidad and Tobago", "Tunisia", "Turkey", "Uganda", "United Kingdom", "United States", "Uruguay", "Venezuela", "Vietnam", "West Bank and Gaza", "Yemen, Rep.", "Zambia", "Zimbabwe"],
#> "sortable": true,
#> "filterable": true,
#> "tags": [],
#> "label": "country",
#> "type": "factor",
#> "varname": "country"
#> },
#> {
#> "levels": ["Africa", "Americas", "Asia", "Europe", "Oceania"],
#> "sortable": true,
#> "filterable": true,
#> "tags": [],
#> "label": "continent",
#> "type": "factor",
#> "varname": "continent"
#> },
#> {
#> "locale": true,
#> "digits": null,
#> "sortable": true,
#> "filterable": true,
#> "tags": [],
#> "label": "Mean of annual life expectancies",
#> "type": "number",
#> "varname": "mean_lifeexp"
#> },
#> {
#> "locale": true,
#> "digits": null,
#> "sortable": true,
#> "filterable": true,
#> "tags": [],
#> "label": "Lowest observed annual life expectancy",
#> "type": "number",
#> "varname": "min_lifeexp"
#> }
#> ],
#> "state": {
#> "layout": {
#> "page": 1,
#> "arrange": "rows",
#> "ncol": 5,
#> "nrow": 3,
#> "type": "layout"
#> },
#> "labels": {
#> "varnames": ["country", "continent", "wiki_link"],
#> "type": "labels"
#> },
#> "sort": [
#> {
#> "dir": "asc",
#> "varname": "continent",
#> "type": "sort"
#> },
#> {
#> "dir": "desc",
#> "varname": "mean_lifeexp",
#> "type": "sort"
#> }
#> ],
#> "filter": [
#> {
#> "values": ["Africa"],
#> "regexp": null,
#> "filtertype": "category",
#> "varname": "continent",
#> "type": "filter"
#> },
#> {
#> "max": 50,
#> "min": null,
#> "filtertype": "numberrange",
#> "varname": "mean_lifeexp",
#> "type": "filter"
#> }
#> ]
#> },
#> "views": [
#> {
#> "name": "Countries with high life expectancy (min >= 60)",
#> "state": {
#> "layout": {
#> "page": 1,
#> "arrange": "rows",
#> "ncol": 3,
#> "nrow": 2,
#> "type": "layout"
#> },
#> "labels": {
#> "varnames": ["continent", "country"],
#> "type": "labels"
#> },
#> "sort": [
#> {
#> "dir": "desc",
#> "varname": "min_lifeexp",
#> "type": "sort"
#> }
#> ],
#> "filter": [
#> {
#> "max": null,
#> "min": 60,
#> "filtertype": "numberrange",
#> "varname": "min_lifeexp",
#> "type": "filter"
#> }
#> ]
#> }
#> }
#> ],
#> "inputs": {
#> "inputs": [
#> {
#> "height": 6,
#> "width": 100,
#> "type": "text",
#> "active": true,
#> "label": "Comments about this panel",
#> "name": "comments"
#> },
#> {
#> "options": ["no", "yes"],
#> "type": "radio",
#> "active": true,
#> "label": "Does the data look correct?",
#> "name": "looks_correct"
#> }
#> ],
#> "storageInterface": {
#> "type": "localStorage"
#> },
#> "feedbackInterface": {
#> "feedbackEmail": "johndoe123@fakemail.net",
#> "includeMetaVars": []
#> }
#> },
#> "paneltype": "img",
#> "panelformat": null,
#> "panelaspect": null,
#> "thumbnailurl": null
#> }