Introduction
This article describes how to create a custom analysis tool, also known as a Standard R widget, in Displayr.
Requirements
- A professional Displayr license.
- An R calculation created from the toolbar via Calculation > Custom Code.
Method - How to create your own custom analysis tool
Step 1: Plan
The first step is to work out whether a custom tool is appropriate for the task you want to perform. In general, the benefit of this type of tool is that you can set up your analysis in a pre-defined way or with selectable options that don't require a user having to delve into code to change. If you are unsure of this approach, please contact Support at support@displayr.com.
When working out whether a custom analysis tool is appropriate, outline what you need to do. Some questions to consider:
- Is the analysis tool likely to be used again?
- How flexible does this tool need to be?
- Is it for a specific data format or does it need to be applied to different formats?
- Could a user potentially apply it to the wrong type of data?
- Is it possible to provide user input controls for all necessary options?
Example:
Let's look at an example where we take the following default table...
... and turn it into a CreateCustomTable
auto-fitting table using custom R code with significance testing arrows:
The R code is as follows:
# get table
tab = table.D2.Income.by.Q3.Preferred.cola
tab = tab[-NROW(tab),-NCOL(tab),]
# create default table to store sig fills
sigs = matrix(0,NROW(tab),NCOL(tab))
# mark -1 for negative sig and 1 for positive sig
sigs[tab[,,"z-Statistic"] < -1.96] = -1
sigs[tab[,,"z-Statistic"] > 1.96] = 1
#create custom table
custom.table = flipFormat::CreateCustomTable(tab[,,"Column %"],
sig.change.arrows = sigs,
sig.arrows.up = "green",
sig.arrows.down = "red",
cell.suffix = "%",
col.widths = "150px",
col.header.fill = "#357EC7",
col.header.font.color = "white",
row.header.fill = "#357EC7",
row.header.font.color = "white",
banded.rows = TRUE,
row.header.pad = 5)
In this code:
- We begin by referencing the name of our input table and removing the last NET columns.
- We then create a matrix table called
sigs
to store the significance testing coding based on the table's z-Statistic where less than -1.96 is -1 and higher than 1.96 is 1. This equates to testing significance at the 95% level. - Finally, we use the
CreateCustomTable
function to set the correct formatting (e.g. colors, widths and padding), as well as apply the significance arrow settings.
See How to Add Statistical Significance to CreateCustomTable R Tables, How to Customize Fonts in a CreateCustomTable R Table and How to Customize Colors on a CreateCustomTable R Table.
But what if we want to allow the user to control the header or significance colors, or swap between highlighting arrows and cells for significance? The below will take us through the various steps to consider when creating a custom analysis tool using this example as a guide.
Step 2: Decide on what input controls to include
As one of the main purposes of an analysis tool is to allow the user to select the options they want to apply in the output, input controls are an essential way of simplifying the process.
Options include:
- Numeric and text fields
- Combo and check boxes
- Drop box controls
- Color pickers
Instead of just adding a long list of controls, we must first consider the following in this scenario:
- Do all
CreateCustomTable
arguments need to be added as user inputs or will some always be fixed? - How should we group the controls?
- Does the current code cater to all the user scenarios we want to cover?
- Do all controls need to be visible at the same time?
- What type of controls are best for each function?
Step 3: Add input controls
In our example, we will create a series of user inputs:
- A drop box control for the input table.
- A text box for the optional width of the row header.
- A combo box for choosing the method of significance highlighting (i.e. arrows or cells).
- Four color pickers for selecting the color of the headers, fonts, and significantly higher or lower results.
These controls will be grouped according to relevance like below:
1. Select your calculation and go to Properties > INPUTS JAVASCRIPT. This is where user controls are added. They are written using JavaScript.
2. We begin by adding a heading to the input form.
3. When using multiple groups, it's often best to then add a group
for the first control(s).
4. Next, add the first user control and take note of its arguments.
5. Set the name
to make it easier to reference in the subsequent steps.
6. Set the label
to be useful for the user.
7. Set the type
of input for drop boxes and alternatives
for combo boxes.
8. Set the default
values so the most common use case is catered to without the user having to do anything. Here we use the settings from the original code.
9. Add a prompt
to aid the user so that when they hover over the control it provides a fuller explanation where necessary.
10. Repeat the above for all required controls and groups.
Here is the code for all user inputs in our tool:
// Add heading
form.setHeading("Custom Table");
// Add first group
form.group("Data Source");
// Add drop box to select your input table
form.dropBox({name: "data",
label: "Input table",
types: ["Table"],
prompt: "Please select your input table"})
// Add second group
form.group("Settings");
// Add text box for setting row header width
form.textBox({name: "rowheaderwidth",
label: "Row header width",
default_value: "150px",
prompt: "Please enter the width in pixels"})
// Add combo box for choosing between arrows and cells
form.comboBox({name: "highlight",
label: "Significance Highlighting:",
alternatives: ["Arrows","Cells"],
default_value: "Arrows",
prompt: "Please select your highlighting method"})
// Add third group
form.group("Colors");
// Add color picker for headers
form.colorPicker({name: "headercolor",
label: "Select your header color",
default_value: "#357EC7",
prompt: "Please select your header color"})
// Add color picker for header font color
form.colorPicker({name: "fontcolor",
label: "Select your font color",
default_value: "white",
prompt: "Please select your font color"})
// Add color picker for displaying significantly higher
form.colorPicker({name: "sigupcolor",
label: "Select your significantly higher color",
default_value: "#90EE90",
prompt: "Please select the color for displaying significantly higher results"})
// Add color picker for displaying significantly lower
form.colorPicker({name: "sigdowncolor",
label: "Select your significantly lower color",
default_value: "#E55451",
prompt: "Please select the color for displaying significantly lower results"})
See How to Add Headings, Groups and Pages to a Custom Analysis Tool, How to Create User Input Fields in a Custom Analysis Tool, How to Set Conditional Controls in a Custom Analysis Tool and How to Set Object Types in DropBox Controls in Custom Analysis Tools.
Step 4: Add control references to R code
We now update our R code by replacing the relevant input and argument references with the user input control names in the previous step.
1. Go back to Properties > R CODE.
data
.tab = data
col.widths = rowheaderwidth,
col.header.fill = headercolor,
col.header.font.color = fontcolor,
row.header.fill = headercolor,
row.header.font.color = fontcolor,
sigs
matrix and the various color arguments will be passed into the relevant argument only, otherwise they will return NULL:sig.change.arrows = if(highlight=="Arrows") sigs else NULL,
sig.change.fills = if(highlight=="Cells") sigs else NULL,
sig.arrows.up = if(highlight=="Arrows") sigupcolor else NULL,
sig.arrows.down = if(highlight=="Arrows") sigdowncolor else NULL,
sig.fills.up = if(highlight=="Cells") sigupcolor else NULL,
sig.fills.down = if(highlight=="Cells") sigdowncolor else NULL,
See How to Reference Controls in a Custom Analysis Tool Using R.
Step 5: Add input validations
Validations can be performed to check, among others, whether the input data conforms to the expected format. Let's look at how we can address the following scenarios for our tool:
- What happens when the input table is different to what we expect?
In the original code we make the assumption that the input table has 3 dimensions: rows, columns and multiple statistics. We also assume that the NET fields are at the end but we can't prevent the user from sorting the table and changing their position.
The solution is to check the dimensions of the table at the start using dim
and use the stop
function to display an error message at the top of our output if the condition is not met:
if(length(dim(tab))!=3) stop("Your input table doesn't have the correct dimensions")
Secondly, we can update the following line of code...
tab = tab[-NROW(tab),-NCOL(tab),]
...to the following so that it removes NET rows and columns no matter their position:
tab = tab[rownames(tab)!="NET",colnames(tab)!="NET",]
- What if the key z-Statistic is not shown in the input table?
If there is no z-Statistic present in our table, we should also display an error message. We can return the statistic names by using the dimnames
function whereby the statistics parameter will be in the third position:
stats = dimnames(tab)[[3]]
if(!"z-Statistic" %in% stats) stop("You must select 'z-Statistic' in your input table")
- What happens when the table's statistic is not Column %?
The original code specifically references using the table's Column % statistic but it is possible that this will be % when looking at a grid table, for example.
The solution is to replace Column %...
flipFormat::CreateCustomTable(tab[,,"Column %"],
...with 1 as the primary table statistic will always be in first position.
flipFormat::CreateCustomTable(tab[,,1],
- Other considerations?
The level of validation will depend on how far you want to go, how likely certain scenarios are, and what is likely to differ from the main use cases.
For example, we know that the input tables will only ever show a percentage, so we can leave the cell.suffix
argument as is to append the % character to each cell. However, you may choose to use a conditional reference instead that automatically updates this argument based on the table primary statistic name.
See How to Hide an Output with a Small Sample Size Using an R Error.
Step 6: Check your code
1. Go through each combination of controls (where appropriate) looking out for any red error messages and orange warnings that should not appear.
2. If you do encounter errors, work out whether you need to further restrict inputs or whether the issue is the code itself, e.g. a misspelled reference.
Here is the updated R code in full:
# get table
tab = data
if(length(dim(tab))!=3) stop("Your input table doesn't have the correct dimensions")
tab = tab[rownames(tab)!="NET",colnames(tab)!="NET",]
# get statistics
stats = dimnames(tab)[[3]]
if(!"z-Statistic" %in% stats) stop("You must select 'z-Statistic' in your input table")
# create default table to store sig fills
sigs = matrix(0,NROW(tab),NCOL(tab))
# mark -1 for negative sig and 1 for positive sig
sigs[tab[,,"z-Statistic"] < -1.96] = -1
sigs[tab[,,"z-Statistic"] > 1.96] = 1
#create custom table
custom.table = flipFormat::CreateCustomTable(tab[,,1],
sig.change.arrows = if(highlight=="Arrows") sigs else NULL,
sig.change.fills = if(highlight=="Cells") sigs else NULL,
sig.arrows.up = if(highlight=="Arrows") sigupcolor else NULL,
sig.arrows.down = if(highlight=="Arrows") sigdowncolor else NULL,
sig.fills.up = if(highlight=="Cells") sigupcolor else NULL,
sig.fills.down = if(highlight=="Cells") sigdowncolor else NULL,
cell.suffix = "%",
col.widths = rowheaderwidth,
col.header.fill = headercolor,
col.header.font.color = fontcolor,
row.header.fill = headercolor,
row.header.font.color = fontcolor,
banded.rows = TRUE,
row.header.pad = 5)
Step 7: Add your analysis tool to Displayr's toolbar menu (for Enterprise users)
Enterprise users have the added option of being able to add custom tools to the Anything menu under your company name. These are stored as RScripts in your Displayr Cloud Drive.
See How to Share a Custom Analysis Tool Between Documents.
Resources: Learning R
Using R in Displayr Video Series
How R Works Differently in Displayr Compared to Other Programs
How to Reference and Distinguish between Different R Objects in Displayr
How to Use Point and Click Inside R Code
How to Use Different Types of Data in R
How to Perform Mathematical Calculations Using R
How to Work with Conditional R Formulas
How to Work with Regular Expressions Using R
How to Use R's Paste Formulas in Displayr
How to Troubleshoot R Code in Displayr
Resources: Learning JavaScript
How to Work with Conditional JavaScript Formulas
How to Manipulate Strings Using JavaScript
How to Work with JavaScript Arrays and Loops
How to Use JavaScript in Displayr
How to Troubleshoot JavaScript Code in Displayr
Series: Learning How to Create Your Own Custom Analysis Tool
1. How to Create an Auto-Updating Custom Analysis Tool
2. How to Add Headings, Groups and Pages to a Custom Analysis Tool
3. How to Create User Input Fields in a Custom Analysis Tool
4. How to Set Conditional Controls in a Custom Analysis Tool
5. How to Set Object Types in DropBox Controls in Custom Analysis Tools
6. How to Reference Controls in a Custom Analysis Tool Using R
Next
How to Create an Auto-Updating Custom Analysis Tool
See Also
How to Use R-based Analysis Tools in Displayr
How to Customize R-based Analysis Tools in Displayr
How to Add Statistical Significance to CreateCustomTable R Tables
How to Customize Fonts in a CreateCustomTable R Table
How to Customize Colors on a CreateCustomTable R Table
How to Hide an Output with a Small Sample Size Using an R Error