Jeeves is your sagacious personal valet to build and maintain predictive tools in Alteryx.
This package provides functions that allows Alteryx users to write, test and manage R code in their workflows, outside of Alteryx, in an IDE like RStudio.
You can install the package binary from github, or build it from source using install_github
.
install.packages("jeeves",
repos = 'http://alteryx.github.io/jeeves'
)
# devtools::install_github("alteryx/jeeves")
Let us start by scaffolding a sample workflow, extracting the embedded R code, editing it in an IDE, and updating the workflow, all without leaving the confines of your favorite IDE.
library(jeeves)
scaffoldWorkflow(outDir = 'test')
This function
test
jeeves
into test/mymacro.yxmc
test/mymacro1.R
.test/mymacro1.R
for editing.The R code in test/mymacro1.R
has been written carefully so that it will run without any errors even outside of Alteryx. You can read more about this in the section on Writing Portable Code
You can now go ahead and edit the contents of test/mymacro1.R
. When you are done editing, you can update the macro by running
insertRcode('mymacro.yxmc', 'mymacro1.R`)
Often times, you might find yourself in a situation where you want to run some R code from an Alteryx workflow in RStudio. You could copy-paste the code from the workflow or alternately, use extractRCode
to extract and save it to file.
If you now try to execute the extracted code in an R session outside of Alteryx, it is most likely to throw an error. Why does that happen? Why does it run fine inside an Alteryx workflow, but errors out when run in an R session outside? There are two primary reasons for this:
Alteryx workflows (especially macros), use interface (UI) tools to receive input from the users at runtime. These inputs can be referenced by name, inside the R tool as %Question.variablename%
. At runtime, a preprocessor replaces these references with their actual values, before executing the code.
Alteryx workflows pass data around from node to node. The R tool can read data from an Alteryx input stream using d <- read.Alteryx("#1", mode = 'data.frame')
. This line of code reads the contents of input stream "#1" and assigns it to the variable d
. All this happens at runtime.
Since the input variables and data streams exist only at runtime inside an Alteryx workflow, any code that makes use of these will throw errors when run outside of Alteryx. The trick to solving this problem is to follow a small set of conventions that will make your R code portable across Alteryx and other R editors.
We use read.Alteryx
to read data into R from an Alteryx input stream. We can make this code portable by making use of read.Alteryx2
, and supplying it with default
data.
d <- read.Alteryx2('#1', default = data.frame(x = 1:10))
The read.Alteryx2
function operates differently depending on the compute context. Inside an Alteryx workflow, it simply calls read.Alteryx
under the hood. Outside an Alteryx workflow, it first looks for a file named .input#1.rds
in the current workflow directory. This file should exist if the workflow was run prior to popping it open into your IDE, since read.Alteryx2
creates it everytime the workflow is run. If this file doesn’t exist, it will use the value provided by the default argument.
If you always run the workflow prior to executing the R code in an R console, you can avoid providing a default
, since the first run would create an rds
file that can then be read by R during subsequent runs. However, I always find it useful to specify a default
, even when this is the case.
This package provides helper functions that let you read different types of questions inputs, and assign them to an R object.
input <- list(
breaks = numericInput("%Question.breaks%", default = 5),
color = textInput("%Question.color%", default = "steelblue")
)
Some additional inputs have been added to handle common design patterns. Suppose, you have a radio input that lets users choose between three distributions.
if ("%Question.dist.normal%" == "True"){
# do something
} else if ("%Question.dist.uniform%" == "True"){
# do something
} else if ("%Question.dist.exp%" == "True"){
# do something
}
With this package, you can use the findTrueInput
function
input <- list(
dist.normal = radioInput("%Question.normal%", TRUE),
dist.uniform = radioInput("%Question.uniform%"),
dist.exponential = radioInput("%Question.exp%")
)
input$dist <- findTrueInput(input, 'dist')
This is an experimental feature that allows automatic extraction of question inputs from an Alteryx workflow and inserting it into the R Code. To test this feature, let us edit mymacro1.R
so as to remove the lines that contain the question inputs.
Your mymacro1.R
file should now be
# read data
d <- read.Alteryx2("#1", default = data.frame(x = 1:10))
# write data to output 1
write.Alteryx2(d, 1)
# write graph to output 3
AlteryxGraph2({hist(d$x, breaks = input$breaks, col = input$color)}, 3)
Let us insert this R code back into the macro
insertRcode('mymacro1.yxmc', 'mymacro1.R')
Now, let us run the extractMacro
function. This time around, we pass it an extra argument named extractInput
, which extracts all question inputs, and generates the necessary code that would convert them into R objects and assign them to a list object with the specified name.
extractRcode('rmacro.yxmc', extractInput = 'input')
You will notice that the following lines automatically got appended to the extracted rmacro1.R
.
## DO NOT MODIFY: Auto Inserted by jeeves ----
library(jeeves)
input <- list(
breaks = numericInput('%Question.breaks%' , 5),
color = textInput('%Question.color%' , 'steelblue'),
debug = checkboxInput('%Question.debug%' , FALSE)
)
options(alteryx.wd = '%Engine.WorkflowDirectory%')
options(alteryx.debug = input$debug)
##----
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.