Author’s note: This interactive manuscript is the accepted pre-print version of my article published in Spatial Demography. The final version of this publication is available at Springer via the following link: http://dx.doi.org/10.1007/s40980-016-0029-1. To cite this article, please refer to the final version at the link.

The code in this article uses the new 4.0 syntax for the plotly package, available in the development version of the package as of this writing; as such, to reproduce the Plotly examples in this article, please install from GitHub with devtools::install_github('ropensci/plotly'). I am very grateful to the R community for creating an ecosystem in which I could write the idbr package and this article; special thanks are due to Carson Sievert and the rest of the Plotly team for their incredible & accessible visualization tool.

Abstract: Data visualization is a core component of the demographer’s workflow, as visualizations are essential to communicate the findings of demographic research. Recent advances in interactive data visualization have made it easier to produce dynamic web-based graphics in a variety of computing environments, including R, a popular tool for demographers. This article illustrates how to produce interactive charts and maps of demographic data in R using Plotly and Shiny, two frameworks for web-based visualization. Data for the examples come from idbr, a new R package to download demographic indicators from the US Census Bureau’s International Data Base.

Introduction

Data visualization has grown in prominence and popularity across a wide variety of fields in recent years (Kirk 2012; Yau 2013). The development of many new interactive visualization tools has accompanied this growing interest in data visualization, enabling users from a wide range of technical backgrounds to visualize and communicate with data interactively. Indeed, interactive visualizations have the potential to enhance user exploration of data and enrich narratives supported by the visualizations (Segel and Heer 2010). This has direct relevance for demography and allied fields. Maps and other visual tools form a core component of disciplinary practice, as they are essential in revealing insights about spatial and temporal aspects of demographic datasets (Abel and Sander 2014; Howell and Porter 2013; Healy and Moody 2014; Dennett 2015). In turn, interactive visualization can enhance the ability of demographers to explore their data during the analytic process and to communicate their results via the web.

The programming language R is well-suited for research in population studies given its strengths in data processing, statistics, and visualization (Sparks 2013; 2014). Over the past two years, new innovations within the R language have made it much easier to generate interactive web-based visualizations directly from R. The htmlwidgets package allows R developers to wrap JavaScript web visualization libraries in R code, which in turn facilitates interactive web visualization directly from R. Additionally, the Shiny framework developed by RStudio lets R users build full-fledged web applications for presenting data analyses and visualizations entirely within R. This has direct relevance for researchers and educators in population studies and demography, as the entire process of data acquisition, data analysis, and visualization can all take place within the same analytical environment and programming language. It is also important given the rising popularity of open-source R in research relative to commercial alternatives like SPSS, SAS, and Stata (Muenchen 2016).

This article provides an overview of this new functionality within R, using examples from the new idbr package (Walker 2016) which gives R users direct access to international demographic indicators from the United States Census Bureau’s International Data Base.

The International Data Base and the idbr R Package

The US Census Bureau’s International Data Base (IDB) includes historical demographic data, current population estimates, and demographic projections to 2050 for countries of population 5,000 or greater that are recognized by the US Department of State (US Census Bureau 2013). Demographic indicators in the IDB include: mid-year population; population counts by sex and age; and fertility, mortality, and migration variables such as net migration, infant mortality rates, and total fertility rates. Future projections of these indicators are estimated using the cohort-component method (US Census Bureau 2013).

Data from the IDB are available via a web interface provided by the US Census Bureau at https://www.census.gov/population/international/data/idb/informationGateway.php, and also can be accessed programmatically via the IDB data application programming interface, or API. The idbr R package provides convenient functions for accessing IDB data within an R session, and converting the data to an R data frame for analysis and visualization. idbr is available on CRAN; R users can install the package with install.packages('idbr').

Users of the Census APIs should request an API key, which is available from http://api.census.gov/data/key_signup.html. The idbr package requires R users to set their API keys prior to accessing the data. The API key can be set for an entire R session with the idb_api_key function:

idb_api_key('5ed58....')  # truncated

Once set, idbr users can access the international demographic indicators available in the IDB. There are two main datasets available in the IDB API: the one-year-age-group dataset, which allows users to fetch population by age for a given country in a given year, and the five-year-age-group dataset, which contains nearly 100 demographic indicators, along with data for five-year age groups as columns.

Access to these two datasets are available in idbr via two separate functions: idb1 for the one-year age group dataset, and idb5 for the five-year age group dataset. The idb1 function includes information on age, country area in square kilometers, and population, which can be subsetted by sex and age group. The idb5 function, on the other hand, includes nearly 100 different variables in the areas of population counts, fertility, mortality, and migration. idbr users can obtain a full list of variables and their definitions by calling idb_variables(); additionally, these variables are grouped into concepts, which can be viewed with the idb_concepts() function.

To call these functions, R users will supply a vector of FIPS 10-4 country codes, or alternatively a vector of valid country names, and a vector of years for which they would like to obtain data, along with the variables and/or concepts they require and any other optional arguments. At its simplest, the idb1 function can be called with a single country and a single year:

library(idbr)

idb_api_key('Your Census API key goes here')

us <- idb1('US', 2016)

head(us)
## # A tibble: 6 x 6
##     AGE AREA_KM2          NAME     POP  FIPS  time
##   <dbl>    <dbl>         <chr>   <dbl> <chr> <dbl>
## 1     0  9147593 United States 4029356    US  2016
## 2     1  9147593 United States 4017346    US  2016
## 3     2  9147593 United States 4004585    US  2016
## 4     3  9147593 United States 3988434    US  2016
## 5     4  9147593 United States 3998839    US  2016
## 6     5  9147593 United States 4026967    US  2016

idb1 returns an object of class tbl_df, which is an enhanced long-form data frame optimized for working with the R package dplyr, which idbr uses internally to process data (Wickham and Francois 2016). Each row represents the total population in a given country for a specified age in a given year, which in the above example includes data for the United States in 2016. This stands in contrast with the idb5 function, which returns a data frame in which each country for a given year represents a row, and age-group data (if requested) or any other variable will be found in the columns.

n_amer <- idb5(c("US", "MX", "CA"), 2016, 
               concept = "Total midyear population by 5-year age groups", 
               country_name = TRUE)

n_amer
## # A tibble: 3 x 24
##     POP0_4 POP10_14 POP100_ POP15_19 POP20_24 POP25_29 POP30_34 POP35_39
##      <dbl>    <dbl>   <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
## 1 20038560 20595524   73173 21140881 22471676 23000966 21863539 20834325
## 2 11255356 11149434    3209 11054415 10766246 10286888  9412897  8618608
## 3  1805929  1850040   25883  1975416  2309298  2371070  2369210  2289323
## # ... with 16 more variables: POP40_44 <dbl>, POP45_49 <dbl>,
## #   POP5_9 <dbl>, POP50_54 <dbl>, POP55_59 <dbl>, POP60_64 <dbl>,
## #   POP65_69 <dbl>, POP70_74 <dbl>, POP75_79 <dbl>, POP80_84 <dbl>,
## #   POP85_89 <dbl>, POP90_94 <dbl>, POP95_99 <dbl>, NAME <chr>,
## #   FIPS <chr>, time <dbl>

Interactively plotting IDB data with Plotly

The htmlwidgets R package (Vaidyanathan et al. 2015), first released in 2015, has enabled R developers to create numerous packages that bind R code to JavaScript libraries and create interactive web-based documents. An example htmlwidget is the plotly R package, which allows users to generate interactive charts, graphs, and maps with the Plotly JavaScript library entirely from R (Plotly Technologies Inc. 2015; Sievert et al. 2016). The syntax of the plotly package is based on the Grammar of Graphics and related to that of the R visualization package ggplot2 (Wilkinson 2005; Wickham 2016).

Plotly includes a wide range of chart types that can be leveraged to visualize the different demographic indicators in the IDB, available via idbr. For example, one common use case might be to visualize how a given demographic variable has changed over time for selected countries. An example is that of life expectancy at birth, which varies significantly around the world and can shift dramatically in the wake of catastrophic events such as disease, famine, war, or political upheavals, as evidenced by the drop in life expectancy that took place in former Soviet Republics after the dissolution of the USSR. In turn, the following example will illustrate how to generate an interactive line chart of trends in life expectancy in Russia, Ukraine, and Belarus during this period.

As FIPS country codes are not always immediately intuitive, idbr uses the countrycode R package (Arel-Bundock 2015) to convert valid country names to FIPS codes when supplied to its functions. Life expectancy at birth is available from the IDB for both sexes and separated by males and females; this example will use the life expectancy for both sexes, which is represented by the variable code 'E0'.

ssr_df <- idb5(c("Russia", "Belarus", "Ukraine"), 1989:2000, 
               variables = "E0", country_name = TRUE)

head(ssr_df)
## # A tibble: 6 x 4
##      E0   NAME  FIPS  time
##   <dbl>  <chr> <chr> <dbl>
## 1 69.14 Russia    RS  1989
## 2 68.81 Russia    RS  1990
## 3 68.57 Russia    RS  1991
## 4 67.55 Russia    RS  1992
## 5 65.19 Russia    RS  1993
## 6 64.15 Russia    RS  1994

The above idb5 call returns a data frame where each row represents the life expectancy of a country in a given year. The data can now be passed to Plotly for interactive plotting. Following its grammar of graphics-inspired design, the visualization is first initialized with the plot_ly() function; the chart type is specified by an appropriate add_*() function; and the chart layout is governed by the layout() function. These functions can be connected with the pipe operator %>% from the magrittr package, allowing users to generate Plotly visualizations as follows.

library(plotly)

plot_ly(ssr_df, x = ~time, y = ~E0, color = ~NAME) %>%
  add_lines() %>%
  layout(xaxis = list(title = "Year"),
         yaxis = list(title = "Life expectancy at birth"))

Figure 1: Line chart of life expectancy at birth for Russia, Ukraine, and Belarus from 1989-2000, produced with Plotly. Data source: US Census Bureau International Data Base.

A minimum amount of code as shown above produces an interactive time-series chart of life expectancy at birth in Russia, Ukraine, and Belarus between 1989 and 2000. In the plot_ly function, the user initializes the plotly object, and specifies the data source followed by the column names to use for the X and Y axis values and how to group the values (the color argument) as formulas. The trace type is then specified with the call to add_lines(). The arguments passed to the layout function then modify the overall appearance of the plot; in this case, new X and Y axis labels are set. Users can hover their cursors over any trace on the chart to get a tooltip with specific information about the data values, and can click entries in the legend to turn data series on or off. Additionally, users can zoom in to specific areas on the chart by clicking and dragging, then double-click to return to the original view. The chart illustrates how life expectancy in the three former Soviet republics fell after 1989, reaching a nadir of 64 in Russia in 1994.

While the idb1 function gives access to fewer variables than the idb5 function, its ability to return population data in one-year age bands by sex makes it well-suited for building population pyramid visualizations. Population pyramids can be constructed in Plotly by plotting two sets of bars, grouped by gender, back-to-back around a central axis of 0. Doing so effectively in Plotly requires setting some additional options, which are detailed below.

The example below will cover how to make a population pyramid for the United Arab Emirates in 2016. As with many other Persian Gulf countries, large numbers of labor migrants – often from South Asia – have come to the country, leading to a gender imbalance with many more men than women at several ages. This gender imbalance is reflected in the country’s population pyramid.

The first step toward building a population pyramid of the UAE involves fetching the requisite data from the IDB, this time with the idb1 function.

library(dplyr)

male <- idb1("United Arab Emirates", 2016, sex = "male") %>%
  mutate(POP = POP * -1,
         SEX = "Male")

female <- idb1("United Arab Emirates", 2016, sex = "female") %>%
  mutate(SEX = "Female")

uae <- rbind(male, female) %>%
  mutate(abs_pop = abs(POP))

In this example, the user makes two calls to idb1: first to fetch data for males, and then to fetch data for females. The population column for males is converted to negative numbers so that it can be plotted on the other side of the vertical axis to females, and the values in the SEX columns are given more specific names (SEX defaults to 1 for males and 2 for females). The two data frames are then combined with the rbind function, and a new column containing the absolute population value is calculated, which will be used in the population pyramid’s hover tooltip. The R user can now produce a population pyramid from the uae data frame with the code below.

plot_ly(uae, x = ~POP, y = ~AGE, color = ~SEX) %>%
  add_bars(orientation = "h",
        hoverinfo = "y+text+name", text = ~abs_pop, 
        colors = c("darkgreen", "red")) %>%
  layout(bargap = 0.1, barmode = "overlay", 
         title = "United Arab Emirates, 2016", 
         xaxis = list(tickmode = "array", 
                      tickvals = c(-150000, -100000, -50000, 0, 50000),
                      ticktext = c("150k", "100k", "50k", "0", "50k"), 
                      title = "Population"), 
         yaxis = list(title = "Age"))

Figure 2: Population pyramid for the United Arab Emirates in 2016, produced with Plotly. Data source: US Census Bureau International Data Base.

As with the life expectancy line chart, the R user defines the basic parameters of the chart in the plot_ly function, specifies the chart type with the add_bars function, and sets up some components of the chart layout in layout. However, the population pyramid requires some additional modifications, represented by the other arguments passed to the add_bars and layout functions. The hoverinfo parameter refers to the content that will appear in the tooltip when the user hovers the cursor over a bar; this is overridden to insert the absolute population value so that all numbers will be positive. Similarly, the tickmode, tickvals, and ticktext options allow for manual customization of the X axis tick labels, which again represent all values as positive numbers.

The third example involves interactive mapping with idbr and Plotly. Plotly has built-in functionality for both point-based mapping, provided that latitude and longitude coordinates are available, and choropleth mapping of country and US state-level data. In this example, as idbr returns country-level demographic indicators, the data from idbr can be mapped with Plotly.

In the example below, the R user generates an interactive map of total fertility rate by country in Africa. To commence, the built-in dataset countrycode_data in the countrycode package includes a column, region, that organizes country codes by sub-region. The code below finds those rows in the data frame that are in Africa, then drops those observations with missing values to generate a vector of African country FIPS codes. This country vector is then passed to the idb5 function, which generates a data frame of total fertility rates in 2016 for countries in Africa.

The africa_tfr data frame generated from idbr is immediately piped to the left_join function from the dplyr package to merge the countrycode_data data frame to it. To identify countries for mapping, Plotly can use country names or the ISO-3C country codes; however the ISO codes, available in the countrycode_data data frame, are likely a safer bet in the instance of inconsistent spelling. Once generated, the R user passes the new africa_tfr data frame to the plot_ly function which is then piped to the add_choropleth function for mapping. The user specifies a z value, which represents the values to be mapped; a column of location codes, passed to the locations parameter, as well as the color scheme to be used. In the layout function, the R user sets the scope of the map to Africa and chooses higher-resolution polygons with 50, representing a scale ratio of 1:50,000,000 (the other option is 110, for 1:110,000,000).

library(countrycode)

africa <- countrycode_data[countrycode_data$continent == "Africa", ]

africa_fips <- na.omit(africa$fips104)

africa_tfr <- idb5(country = africa_fips, year = 2016, 
                   variables = "TFR", country_name = TRUE) %>%
  left_join(countrycode_data, by = c("FIPS" = "fips104"))

plot_ly(africa_tfr, z = ~TFR, text = ~NAME, locations = ~iso3c) %>%
  add_choropleth(colors = "Purples", hoverinfo = "z+text") %>%
  layout(geo = list(scope = "africa", resolution = 50),
         title = "Total fertility rate in Africa, 2016")

Figure 3: Choropleth map of total fertility rate by country in Africa in 2016, produced with Plotly. Data source: US Census Bureau International Data Base.

The resultant map shows geographic variations in TFR in Africa; it is pannable and zoomable by the user, with information about the countries available in a hover tooltip.

Once generated, R users have multiple ways to save their Plotly plots. Inside of RStudio, the easiest way to do this is to choose Export -> Save as Web Page in the RStudio Viewer, and specify an output HTML file on disk. Any Plotly plot can also be saved to an HTML file with the saveWidget function from the htmlwidgets package. The user should first assign the Plotly plot to a variable, then pass this variable to the saveWidget function. For example, the following code below assumes the map of Africa has been assigned to a variable africa_map, then saves this map to the user’s working directory.

library(htmlwidgets)

saveWidget(africa_map, "africa_map.html")

Afterwards, the HTML file can be uploaded to a web server for sharing. If a web server is unavailable, however, R users can also publish plots to Plotly’s cloud, provided that the user has established a Plotly account at https://plot.ly/. Users can sign up for accounts directly from R with the signup function in the plotly package; if an account already exists, users can authenticate their credentials by modifying environment variables as in the code below.

Sys.setenv("plotly_username" = "Your username goes here")
Sys.setenv("plotly_api_key" = "Your API key goes here")

plotly_POST(africa_map, "tfr_in_africa")

The plot now is hosted in Plotly’s cloud with a distinct URL for sharing, and can be further modified using Plotly’s web graphical user interface.

Figure 4: Choropleth map of Africa as it appears in a user’s Plotly web account.

Interactive web applications in R with Shiny

The idbr and plotly R packages allow R users to generate interactive plots of international demographic indicators with a minimal amount of R code, making them suitable for both practitioners and educators who might wish to present information concerning international demographic trends and issues. However, as they still require programming in R, non-coders are limited in their ability to interact with the package. The shiny package, developed by RStudio (Chang et al. 2015), fills this gap. With Shiny, R users can developed web-based graphical user interfaces around their R analyses and visualizations, then publish the interfaces to allow others to interact with and visualize the data themselves. In turn, Shiny is a useful tool for demographic practitioners who wish to share their analyses with a broader audience.

Shiny applications consist of two principal components: a server, which dictates the ways in which the data will be processed, analyzed, and visualized, and a user interface, which concerns the overall look of the Shiny application. By convention, Shiny applications include server code in an R script server.R, and user interface code in a separate script ui.R; the two can be combined in one app.R script as well. The example below will cover a basic use case of Shiny alongside idbr and Plotly.

The code below produces a Shiny application that generates a time series line chart, much like the example in Figure 1. The main difference here is that a Shiny application can allow the user to interactively modify the properties of the chart rather than having to specify it in code. In this basic example, the Shiny application includes a drop-down menu from which the application user can select countries to add to the line chart, as well as a range slider to specify the years that the chart will cover.

To get started, the Shiny application developer might want to download the requisite data from the IDB beforehand to improve performance of the app. Often, developers will distribute pre-processing code in a script titled setup.R. In this instance, the developer uses idbr to fetch infant mortality data for all countries in the database from 1990 to 2050, then saves the dataset to an RDS file to be read in by the Shiny application.

# setup.R

library(idbr)

idb_api_key("5ed58....") # truncated

df <- idb5(country = "all", year = 1990:2050,
     variables = "IMR", country_name = TRUE)

saveRDS(df, "imr.rds")

Next, the developer prepares the server script, which reads in the data fetched by idbr then defines functions for the application. The server code in server.R is below.

library(shiny)
library(plotly)
library(dplyr)

df <- readRDS("imr.rds")

function(input, output) {

  linechart_data <- reactive({

    out <- df %>%
      filter(NAME %in% input$country,
             time %in% input$years[1]:input$years[2])

    return(out)

  })

  output$linechart <- renderPlotly({

    plot_ly(linechart_data(), x = ~time, y = ~IMR, color = ~NAME) %>%
      add_lines() %>%
      layout(xaxis = list(title = "Year"),
             yaxis = list(title = "Infant mortality rate"))

  })

}

In the server script, the Shiny developer loads the requisite packages, then specifies the Census API key to fetch data from the IDB API. The server function has two arguments: input and output, which concern what inputs the server will take in, and what it will give back. Inside of this function, the developer defines a reactive data frame function, linechart_data, that will contain a data frame to be plotted by Plotly. However, as country is set to input$country and the range passed to year is set to the elements specified by input$years, the data frame function linechart_data will filter the master data frame df and re-generate itself each time in response to user input. The second reactive element, output$linechart, will be generated by Plotly in response to the countries passed to it, and rendered by renderPlotly.

This server script will communicate with the user interface script in ui.R found below.

library(shiny)
library(plotly)

df <- readRDS("imr.rds")

fluidPage(

  titlePanel("Infant mortality rate, selected countries"),

  sidebarLayout(
    sidebarPanel(
       selectInput("country",
                   "Select countries to plot:",
                   choices = sort(unique(df$NAME)),
                   multiple = TRUE,
                   selected = "Ghana"),
       sliderInput("years",
                   "Select a range of years",
                   min = 1990,
                   max = 2050,
                   value = c(2000, 2020),
                   sep = "")
    ),

    mainPanel(
       plotlyOutput("linechart")
    )
  )
)

The user interface script is configured so that the application will collect appropriate values that are passed to the Shiny server. The script specifies that the application will include a sidebar with a country selector; as the first argument in the selectInput function is "country", Shiny will know to pass the selected value to input$country defined in the server. Similarly, a range slider created with the sliderInput function will send values to input$years contained in the server script. The script then directs Shiny to put the rendered line chart, identified as "linechart" in the plotlyOutput function and produced by renderPlotly in the server script, in the main panel of the application.

Figure 5: Example Shiny application to interact with infant mortality data retrieved with the idbr package.

The result, represented in the image above, is an interactive application in which the user can select different countries and compare their past and projected infant mortality rates. The plot itself is a fully interactive Plotly visualization, with hover tooltips and an interactive legend that can be used to filter the data series in the plot; however, the user can now choose any of the countries in the International Data Base to visualize. Once finished building the Shiny application, the author can publish the application to the web using RStudio’s ShinyApps.io hosting service, which offers free accounts to get started. A live version of the application is accessible at https://walkerke.shinyapps.io/idbr-line/.

Summary

Data visualization is a key component of the demographer’s workflow, as it assists with the exploration of data when performing analysis as well as the communication of results. In turn, interactive data visualization provides additional tools for demographers for data exploration, and helps with the production of graphics that are optimized for dissemination on the web. In this article, I have used the idbr R package as an example to visualize international demographic indicators; however, these examples could be applied in any realm of demographic analysis. For example, a demographic researcher could use a Shiny application to interactively present the performance of a model under different scenarios, or a demographic office could build an application for custom demographic dashboards for presentation to the public. The examples in this article also illustrate how the R ecosystem allows demographers to conduct data preparation, modeling, interactive visualization, and even publishing of results in the same computing environment.

References

Abel, G.J., and Sander, N. (2014). Quantifying Global International Migration Flows. Science 343(6178), 1520-1522.

Arel-Bundock, V. (2014). countrycode: Convert Country Names and Country Codes. https://cran.r-project.org/web/packages/countrycode/index.html.

Chang, W., Cheng, J., Allaire, J., Xie, Y., and McPherson, J. (2015). shiny: Web Application Framework for R. https://cran.r-project.org/web/packages/shiny/index.html.

Dennett, A. (2015). Visualising migration: Online tools for taking us beyond the static map. Migration Studies 3(1), 143-152.

Healy, K., and Moody, J. (2014). Data Visualization in Sociology. Annual Review of Sociology 40, 105-128.

Howell, F.M., and Porter, J.R. (2013). Editorial Welcome: Why Spatial Demography? Spatial Demography 1(1), 1-2.

Kirk, A. (2012). Data visualization: a successful design process. Birmingham: Packt Publishing.

Muenchen, B. (2016). R Passes SAS in Scholarly Use (finally). r4stats.com, June 8. http://r4stats.com/2016/06/08/r-passes-sas-in-scholarly-use-finally/. Last accessed 7 July 2016.

Plotly Technologies Inc. (2015). Collaborative data science. Montre´al, QC. https://plot.ly.

R Core Team (2015). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/.

Sievert, C., Parmer, C., Hocking, T., Chamberlain, S., Ram, K., Corvellec, M., and Despouy, P. (2016). plotly: Create Interactive Web Graphics via Plotly’s JavaScript Graphing Library. https://cran.r-project.org/web/packages/plotly/index.html

Segel, E., and Heer, J. (2010). Narrative Visualization: Telling Stories with Data. IEEE Transactions on Visualization & Computer Graphics 16(6), 1139-1148.

Sparks, C. (2013). Spatial Analysis in R: Part 1: Getting data from the ACS into R and Exploratory Data Analysis. Spatial Demography 1(1), 131-139.

Sparks, C. (2014). Measuring Residential Segregation using R: So Long to Factfinder. Spatial Demography 2(1), 72-78.

US Census Bureau (2013). International Data Base Population Estimates and Methodology. http://www.census.gov/population/international/data/idb/estandproj.pdf.

Vaidyanathan, R., Xie, Y., Allaire, J., Cheng, J, and Russell, K. (2015). htmlwidgets: HTML Widgets for R.

Walker, K. (2016). idbr: R Interface to the US Census Bureau International Data Base API. R package version 0.2. https://CRAN.R-project.org/package=idbr.https://cran.r-project.org/web/packages/htmlwidgets/index.html.

Wickham, H. (2010). A Layered Grammar of Graphics. Journal of Computational and Graphical Statistics 19(1), 3-28.

Wickham, H. (2016). ggplot2: Elegant Graphics for Data Analysis, Second Edition. New York: Springer.

Wickham, H., and Francois, R. (2016). dplyr: A Grammar of Data Manipulation. R package version 0.5.0. https://CRAN.R-project.org/package=dplyr

Wilkinson, L. (2005). The Grammar of Graphics, Second Edition. New York: Springer.

Yau, N. (2013). Data Points: Visualization That Means Something. Indianapolis, IN: John Wiley & Sons.