The world’s leading publication for data science, AI, and ML professionals.

How to Make Impressive Dashboards in Under 10 Minutes with Shiny

Dashboard development doesn't have to be hard.

Photo by AbsolutVision on Unsplash
Photo by AbsolutVision on Unsplash

Dashboards allow you to structure reports intuitively and break them down into easy-to-read chunks. As a result, end-users can navigate and explore data much easier than with traditional reports.

The shinydashboard R package has been out for ages, and it is a good option with a decent amount of features. However, apps built with it tend to look alike – especially if you’re using it daily on multiple projects.

A lot of simplistic, aesthetically identical dashboards can leave a bad impression on clients and stakeholders. That’s where semantic.dashboard comes into play.

You can download the source code of this article here.

This article is structured as follows:

  • Installation and building your first dashboard
  • Build a fully interactive dashboard
  • Conclusion

Installation and your first dashboard

The semantic.dashboard package is available on CRAN (Comprehensive R Archive Network). To install it, execute the following line from the R console:

install.packages("semantic.dashboard")

You can now proceed by creating an empty dashboard:

library(shiny)
library(semantic.dashboard)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(sidebarMenu()),
  dashboardBody()
)

server <- function(input, output) { }

shinyApp(ui, server)

Here’s the corresponding output:

Image 1 - Empty shiny.semantic dashboard (image by author)
Image 1 – Empty shiny.semantic dashboard (image by author)

The semantic.dashboard‘s app UI is made of a dashboardPage, which is further split into three elements:

  1. HeaderdashboardHeader
  2. SidebardashboardSidebar
  3. BodydashboardBody

This structure is identical as with shinydashboard – making things easier to learn. Let’s see how to tweak all of them.

There are a lot of things you can do with dashboardHeader. For example, you can change the color by specifying a value for the color parameter. You could also include a logo by setting logo_path and logo_allign parameters. If you want to remove the header, specify disabled = TRUE.

Here’s how to change the color from white to something less boring:

dashboardHeader(color = "blue", inverted = TRUE)

The inverted parameter sets the color to the header background instead of the header text.

Here’s the corresponding output:

Image 2 - Styling the header of the semantic dashboard (image by author)
Image 2 – Styling the header of the semantic dashboard (image by author)

Next, let’s see how to add elements to the dashboardSidebar. You can specify the sidebar size by tweaking the side parameter (left by default). You can also tweak the size, which you’ll see how in a minute. Finally, you can altogether disable the sidebar by setting disable = TRUE.

Here’s how to make the sidebar wider:

dashboardSidebar(
  size = "wide",
  sidebarMenu(
    menuItem(tabName = "panel1", text = "Panel 1"),
    menuItem(tabName = "panel2", text = "Panel 2")
  )
)

Here are the results:

Image 3 - Styling the sidebar of the semantic dashboard (image by author)
Image 3 – Styling the sidebar of the semantic dashboard (image by author)

That adds the elements to the sidebar, but how can you display different content when the tab is clicked? That’s where tweaks to dashboardBody come into play.

Let’s add tabItems and two tabs, corresponding to two options in the sidebar. The first option is selected by default, as specified with the selected parameter. Only a single text box should be visible on both panels, indicating which panel you’re currently on. Here’s the code snippet:

dashboardBody(
  tabItems(
    selected = 1,
    tabItem(
      tabName = "panel1",
      textOutput(outputId = "text1")
    ),
    tabItem(
      tabName = "panel2",
      textOutput(outputId = "text2")
    )
  )
)

To make this work, you’ll need to make some tweaks to the server function. You’ll have to render text on the corresponding outputs. Here’s how:

server <- function(input, output) {
  output$text1 <- renderText("This is Panel 1")
  output$text2 <- renderText("This is Panel 2")
}

Your dashboard should look like this now:

Image 4 - Initial dashboard with two panels (image by author)
Image 4 – Initial dashboard with two panels (image by author)

Now you know the basics of semantic.dashboard. Let’s see how to take it a step further and display an interactive data-driven map.


Build a fully interactive dashboard

R comes with a lot of built-in datasets, quakes being one of them. It shows geolocations of 1000 seismic events that occurred near Fiji since 1964. Here’s what the first couple of rows look like:

Image 5 - First couple of rows of the Quakes dataset (image by author)
Image 5 – First couple of rows of the Quakes dataset (image by author)

You’ll now see how to develop a semantic dashboard with the following tabs:

  • Interactive map – display geographical area near Fiji with markers representing the magnitude of the seismic event
  • Table – shows the source dataset formatted as a table

You’ll create the interactive map with the leaflet package, so make sure to have it installed:

install.packages("leaflet")

The UI follows the pattern discussed in the previous section – there’s a header, sidebar, and a body. The header will be empty this time. Most of the differences are in the dashboardBody. The structure should look familiar, but there are two new functions:

  • leafletOutput() – used to display the interactive map
  • dataTableOutput() – used to display the data table

To make the map as large as possible, you can set some inline CSS styles. In the code below, the height is modified, so the map always takes almost the entire screen height (- 80 pixels as a margin).

Here’s the code for the UI:

library(leaflet)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    size = "wide",
    sidebarMenu(
      menuItem(tabName = "map", text = "Map", icon = icon("map")),
      menuItem(tabName = "table", text = "Table", icon = icon("table"))
    )
  ),
  dashboardBody(
    tabItems(
      selected = 1,
      tabItem(
        tabName = "map",
        tags$style(type = "text/css", "#map {height: calc(100vh - 80px) !important;}"),
        leafletOutput("map")
      ),
      tabItem(
        tabName = "table",
        fluidRow(
          h1("Quakes Table"),
          semantic_DTOutput("quakesTable")
        )
      )
    )
  )
)

To make this dashboard work, you’ll have to modify the server function. Inside it lies the code for rendering both the map and the table. The coordinates for the map were chosen arbitrarily, after a quick Google search.

The magnitude of the seismic activity determines the size of a marker. Every marker is clickable – showing the magnitude, depth in kilometers, and the number of stations that reported the seismic activity.

Here’s the code for the server:

server <- function(input, output) {
  output$map <- renderLeaflet({
    leaflet() %>%
      setView(lng = 179.3355929, lat = -20.4428959, zoom = 6.5) %>%
      addProviderTiles("Esri.WorldStreetMap") %>%
      addCircles(
        data = quakes,
        radius = sqrt(10^quakes$mag) * 30,
        color = "#000000",
        fillColor = "#ffffff",
        fillOpacity = 0.5,
        popup = paste0(
          "<strong>Magnitude: </strong>", quakes$mag, "<br>",
          "<strong>Depth (km): </strong>", quakes$depth, "<br>",
          "<strong>Num. stations reporting: </strong>", quakes$stations
        )
      )
  })

  output$quakesTable <- DT::renderDataTable(
    semantic_DT(quakes)
  )
}

And here’s the final dashboard:

Image 6 - Final Quakes dashboard (image by author)
Image 6 – Final Quakes dashboard (image by author)

Conclusion

In this short hands-on guide, you’ve learned how to develop simple and aesthetically-pleasing Shiny dashboards. You’ve learned what semantic.dashboard is, what it brings to the table, and how to pair it with other libraries to produce stunning and intuitive dashboards.

Looking for inspiration? Check out component demos and complete dashboards here.

Join my private email list for more helpful insights.


Loved the article? Become a Medium member to continue learning without limits. I’ll receive a portion of your membership fee if you use the following link, with no extra cost to you.

Join Medium with my referral link – Dario Radečić


Originally published at https://appsilon.com on December 3, 2020.


Related Articles