Red Oak Strategic

  • Home
  • About Us
  • Services
  • Blog
Contact Us
Daina Andries
Wednesday, 17 October 2018 / Published in Analytics, Code, Data, Data Science, Data Visualizations, JavaScript, Machine Learning, R, R-Shiny, Tutorials

Customizing Click Events: How to Capture and Store Data from JavaScript Objects in R Variables

Interaction Design for Data Exploration

Visualizations capable of launching detail views can add value to a data analyst’s user experience. Programming in this kind of interaction automates the creation of complementary charts and increases ease of exploration by linking varied views of the data in a logical way.

This tutorial offers a quick example of how to create a click input function with Shiny.onInputChange  in JavaScript. The visualization used for this example is a heatmap drawn with Highcharts, since the hc_add_event_point  function in the R library highcharter  does not apply for clicks on heatmaps as of this writing. A similar approach can likewise be applied to any visualization drawn with highcharter , whenever the data retrieved and sent from a JavaScript object to R requires customization.

R
1
2
3
4
5
library(shiny)
library(highcharter)
library(ggplot2)
 
red_wine <- read.csv('winequality-red.csv', sep = ';')

Sample Visualization: Correlation Matrix

Exploring relationships among variables in a dataset is an important first step in getting to know and prepping data for machine learning.

Whenever a cell is clicked on the correlation matrix below, the graph will yield a scatter plot of the two variables corresponding to that specific correlation value.

The Wine Quality dataset from the University of California, Irvine data archive for machine learning datasets was used. The data can be downloaded here.

Sending the Data from JavaScript to Shiny

The chart above requires the following R libraries:

R
1
2
3
library(shiny)
library(highcharter)
library(ggplot2)
We read in the data as red_wine :
R
1
red_wine <- read.csv('winequality-red.csv', sep = ';')
From there, generating the heatmap with highcharter  is simple. In the code for our simple Shiny app below, we apply the cor  function to the data, then pass the resulting matrix to hchart .

We add the JavaScript function that extracts the x and y data series names from the correlation matrix inside hc_plotOptions  as a click event. The event  parameter is a matrix cell click, a JavaScript object we can deconstruct. Using this object that we have named event , we create the xstr  and ystr  variables.

From there, we can build the data structure to be returned: an array called data  with the variables x , y , and nonce . The nonce  variable, simply a random number, is commonly used in click interactions: its purpose is to allow for two consecutive clicks on the same element. Otherwise, the event  data will be the same as before, and JavaScript will not interpret this event  as a change, remaining unresponsive until the user clicks on a different element.

We call the JavaScript function Shiny.onInputChange  to send a custom message from JavaScript to Shiny. The first parameter matrix_click  is the unique name for the event which Shiny observers and reactive functions can listen for. We can now refer to the event as input$matrix_click  elsewhere in our code, as we would for other Shiny inputs. The second parameter, data , is the custom message to be sent from JavaScript to R after every click event.

R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
shinyApp(
  ui <- fluidPage(
  
   # Application title
   titlePanel("Red Wine Quality")
  
   , fluidRow(column(8
                     , highchartOutput('wine_corr', height = "600px")
                     )
              )
   ),
  
  server <- function(input, output, session) {
  
  # remove `quality` rating
  red_wine <- subset(red_wine, select = -quality)
  red_wine_corr <- cor(red_wine)
  
  output$wine_corr <- renderHighchart({
    hchart(red_wine_corr) %>%
      hc_plotOptions(
        series = list(
          boderWidth = 1,
          dataLabels = list(enabled = FALSE),
          events = list(
            click = JS("function(event) {
                      
                         var xstr = event.point.series.xAxis.categories[event.point.x].toString();
                         var ystr = event.point.series.yAxis.categories[event.point.y].toString();
  
                         var data = {
                            x: xstr,
                            y: ystr,
                            nonce: Math.random()
                          };
  
                         Shiny.onInputChange('matrix_click', data);
 
                       }"))
          )
        )
  })
  
  #  event listener
  observeEvent(input$matrix_click, {
    
    # retrieve series from red_wine using x and y variables from click data
    red_wine$x_val <- red_wine[[input$matrix_click$x]]
    red_wine$y_val <- red_wine[[input$matrix_click$y]]
    
    # code for ggplot scatter plot
    output$scatterPlot <- renderPlot({
      ggplot(red_wine, aes(x=x_val, y=y_val)) + geom_point() +
        ylab(input$matrix_click$y) + xlab(input$matrix_click$x)
    })
    
    # overlay with ggplot scatter plot
    showModal(
      modalDialog(
        fluidRow(
          column(12,
                 h3(paste0(input$matrix_click$y, " ~ ", input$matrix_click$x))
          )
        )
        , plotOutput("scatterPlot")
        , size = "l"
        , easyClose = TRUE
      )
    )
  })
  
},
 
options = list(
    width = "100%", height = 750
  )
 
)

We can now capture the variable names for any given value in the correlation matrix as a click input. Using these variable names to access the original data series, Shiny can spin up scatter plots on the fly. Not only can we compare correlation values by looking at the cell colors of the correlation matrix, we can also zero in on the shape of variable relationships of interest. A different, more detailed view of the data is just a click away.

  • Tweet
Tagged under: Analytics, Code, Data Science, JavaScript, R, R Shiny, Tutorials

What you can read next

Analytics at Scale: h2o, Apache Spark and R on AWS EMR
Exploratory Data Analysis of the CDC’s ‘500 Cities Project’ – Part 1
Tracking Coronavirus: Building Parameterized Reports to Analyze Changing Data Sources

4 Comments to “ Customizing Click Events: How to Capture and Store Data from JavaScript Objects in R Variables”

  1. Emeka says :Reply
    April 24, 2019 at 11:10 pm

    Very useful option, thanks for sharing. I tried your code using a scatter plot instead of a heatmap and couldn’t get it to work. Any ideas why?

    1. Daina Andries says :Reply
      April 25, 2019 at 11:34 am

      Hello Emeka, you should certainly be able to launch a new graphic from a click on a point in a scatter plot. If you can provide a reproducible example of your code, I would be happy to look into why it’s not working with you.

  2. Binit says :Reply
    June 24, 2019 at 7:15 am

    Hi Daina,

    I wanted to point a dynmic page url for every time when ever User click on a Barchart, i have a list build = [1,2,3], so for three barchart i want to print 1, for first, 2 for 2nd barchart and so on, can you please help me.

    plotOptions: {
    series: {

    stacking: ‘normal’,
    // dataLabels: {
    // enabled: true,
    cursor: ‘pointer’,
    events: {
    click: function (build) {
    location.href = ‘http://192.168.6.1/ + build[1]  +test_result_failures.html/’;
    // }
    }
    }
    }
    },

    1. Daina Andries says :Reply
      June 25, 2019 at 9:21 am

      Hi Binit,

      The best way to do what you’re describing would be to bind the data from your list to the chart itself. That way when you click the chart, you can simply return the url that you have bound to your chart object. It looks like you’re coding in JS, but I have quickly thrown together a bar chart in Highcharter for Shiny R by way of example. The list data is concatenated with the root url on click and returns the unique url for the clicked bar:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      library(highcharter)
      library(htmlwidgets)
      library(shiny)
       
      ydata = c(1,6,3,4,6,7,2,1,1,1,4)
      xdata =  c(1:11)
      url = 'https://www.this_is_your_url/'
       
      df = data.frame("Place" = xdata, "Counts" = ydata, "Place_url" = url)
       
      ui <- fluidPage(
        
        fluidRow(highchartOutput("bar"))
        
      )
       
      server <- function(input, output, session) {
       
       
          output$bar <- renderHighchart({
           
             highchart() %>%
                hc_add_series(df, type="column"
                              , hcaes(x="Place", y="Counts")
                              , name="Counts") %>%
               hc_plotOptions(
                  series = list(
                   borderWidth = 1,
                   dataLabels = list(enabled = FALSE),
                   events = list(
                    click = JS("function(e) {
                                
                                      var counts = e.point.Counts;
                                      var place = e.point.Place;
                                      var url_root = e.point.Place_url;
                                  
                                      var url = url_root + place;
                                  
                                      var data = {
                                          counts: counts,
                                          place: place,
                                          url: url,
                                          nonce: Math.random()
                                       };
            
                                     Shiny.onInputChange('bar_click', data);
          
                                  }"))
              )
            )
        })
        
        observeEvent(input$bar_click,{
           showModal(
              modalDialog(
                 fluidRow(
                    column(12,
                            h3(paste0("URL for Place ", as.character(input$bar_click$place)))
                    )
                 )
                , p(input$bar_click$url)
                , size = "s"
                , easyClose = TRUE
             )
           )
         })
        
      }
       
      shinyApp(ui = ui, server = server)


      Hope this helps.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Tracking Coronavirus: Building Parameterized Reports to Analyze Changing Data Sources

    The pace of our modern world, and the impressiv...
  • Draw Rotatable 3D Charts in R Shiny with Highcharts and JQuery

    While it might be tempting to liven up a report...
  • Analytics at Scale: h2o, Apache Spark and R on AWS EMR

    At Red Oak Strategic, we utilize a number of ma...
  • Time Series Forecasting with Machine Learning: An example from Kaggle

    Introduction This post will demonstrate how to ...
  • Blockchain from a Data Science Perspective

    Imagine someone were to mint a new coin and giv...

Categories

  • Analytics
  • Blockchain
  • Code
  • Data
  • Data Science
  • Data Visualizations
  • Databases
  • Excel
  • Financial Analytics
  • Forecasting
  • JavaScript
  • Machine Learning
  • Political Analytics
  • Predictive Analytics
  • Python
  • R
  • R-Shiny
  • Tutorials
  • Uncategorized
TOP

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.