Inside the enterprise, a dashboard is expected to have up-to-the-minute information, to have a fast response time despite the large amount of data that supports it, and to be available on any device. An end user may expect that clicking on a bar or column inside a plot will result in either a more detailed report, or a list of the actual records that make up that number. This article will cover how to use a set of R packages, along with Shiny, to meet those requirements.
The code
A working example for the dashboard pictured above is available here: Flights Dashboard. The example has all of the functionality that is discussed in this article, except the database connectivity. The code for the dashboard is available in this Gist: app.R
The code for the dashboard that actually connects to a database is available in this Gist: app.R
Begin with shinydashboard
The shinydashboard package has three important advantages:
Provides an out-of-the-box framework to create dashboards in Shiny. This saves a lot of time, because the developer does not have to create the dashboard features manually using “base” Shiny.
Has a dashboard-firendly tag structure. This allows the developer to get started quickly. Inside the dashboardPage()tag, the dashboardHeader(), dashboardSidebar() and dashboardBody() can be added to easily lay out a new dashboard.
It is mobile-ready. Without any additional code, the dashboard layout will adapt to a smaller screen automatically.
Quick example
If you are new to shinydashboard, please feel free to copy and paste the following code to see a very simple dashboard in your environment:
library(shinydashboard)
library(shiny)
ui %
rename(origin_name = name) %__%
select(-lat, -lon, -alt, -tz, -dst) %__%
left_join(tbl(con, &quot;airports&quot;), by = c(&quot;dest&quot; = &quot;faa&quot;)) %__%
rename(dest_name = name) The dplyr variable can then be used in more than one Shiny output. A second example is in the code used to build the highcharter plot below.
output$total_flights % # Use pull to get the total count as a vector
as.integer()
valueBox(value = prettyNum(result, big.mark = &quot;,&quot;),
subtitle = &quot;Number of Flights&quot;)
})
Drill down
The idea of a “drill-down” action is that the end user is able to see part or all of the data that makes up the aggregate result displayed in the dashboard. A “drill-down” action has two parts:
A dashboard element that displays a result is clicked. The result is usually aggregate data.
A new screen is displayed with another report. The new report could be another report showing a lower-level aggregation, or it could show a list of rows that make up the result.
A dashboard element is clicked
The following is one way that capturing a click event is possible. The idea is to display the top airport destinations for a given airline in a bar plot. When a bar is clicked, the desired result is for the plot to activate a drill-down. The highcharter package will be used in this example.
To capture a bar-click event in highcharter, a small JavaScript needs to be written. The example below could be used in most cases, so you can copy and paste it as-is into your code. The variable name and the input name (bar_clicked) would be the only two statements that would have to be changed to match your chart.
js_bar_clicked % collect %__%
head(10) highchart() %__%
hc_add_series(
data = result$n, type = &quot;bar&quot;,
name = paste(&quot;No. of Flights&quot;),
events = list(click = js_bar_clicked)) %__% # The JavaScript variable is called here
hc_xAxis(
categories = result$dest_name, # Value in event.point.category
tickmarkPlacement=&quot;on&quot;)})
Using appendTab() to create the drill-down report
The plan is to display a new drill-down report every time the end user clicks on a bar. To prevent pulling the same data unnecessarily, the code will be smart enough to simply switch the focus to an existing tab if the same bar has been clicked on before.
The new, and really cool, appendTab() function is used to dynamically create a new Shiny tab with a DataTable that contains the first 100 rows of the selection. A simple vector, called tab_list, is used to track all existing detail tabs. The updateTabsetPanel() function is used to switch to the newly or previously created tab.
The observeEvent() function is the one that “catches” the event executed by the JavaScript, because it monitors the bar_clicked Shiny input. Comments are added to the code below to cover more aspects of how to use these features.
tab_list %
walk(~removeTab(&quot;tabs&quot;, .x))
tab_list