Search code examples
c++rrcpptableau-apirserve

Error when calling Rcpp function from Tableau. How to interpret and debug Rserve logs?


I'm having a lot of trouble connecting an R function I wrote to Tableau. The function relies on Rcpp.

In R, if I call prob_1_beats_2(1, 2, 3, 4) it works just fine. However, when I try to connect to Tableau using Rserve, I get this error:

Error in eval(expr, envir, enclos) : expecting a single value

which I cannot seem to trace down. I tried running Rserve in debug mode but to no avail. I'm unsure how to interpret these results. It would be nice to traceback exactly what is being called in R.

Gist of debug logs: https://gist.github.com/FrankPortman/f5cfe32596fd47080286

prob_1_beats_2 <- function(alpha_1, beta_1, alpha_2, beta_2, percent_lift = 0) {

  if(alpha_1 / beta_1 < alpha_2 / beta_2) {

    t1 <- alpha_2
    t2 <- beta_2

    alpha_2 <- alpha_1
    beta_2 <- beta_1

    alpha_1 <- t1
    beta_1 <- t2

  }

  alt_count(alpha_1, beta_1, alpha_2, beta_2)

}

And here is the Rcpp function:

double alt_count(double alpha_1, double beta_1, double alpha_2, double beta_2) {

  double total = 0;

  for(int i = 0; i < alpha_1; i++) {

    total += exp(i * log(beta_1) + alpha_2 * log(beta_2) - (i + alpha_2) * log(beta_1 + beta_2) - log(i + alpha_2) - lbeta(i + 1, alpha_2));

  }

  return total;

}

As you can see:

> prob_1_beats_2(1, 2, 3, 4)
[1] 0.7037037

Finally, the Tableau call I am using:

SCRIPT_REAL("library(mypackage);prob_1_beats_2(.arg1, .arg2, .arg3, .arg4)", 1.0, 2.0, 3.0, 4.0)

Note that

SCRIPT_REAL("library(mypackage);prob_1_beats_2(1, 2, 3, 4)", 1.0, 2.0, 3.0, 4.0)

does return 0.7037037. The real Tableau call I will be using will not use constant values of 1:4 but I am trying this for debugging purposes.


Solution

  • It seems that Tableau was always passing values into R as vectors. When typing:

    SCRIPT_REAL("library(mypackage);prob_1_beats_2(.arg1, .arg2, .arg3, .arg4)", 1.0, 2.0, 3.0, 4.0)
    

    R was actually getting c(1 , 1 , 1 , 1 , etc.), c(2 , 2 , 2 , 2 , 2 , etc.) and so on as arguments to the function. For some reason this was handled without the Rcpp component, but failed when I rewrote the function to include Rcpp.

    This workaround seems to be fine for now:

    prob_1_beats_2 <- function(alpha_1, beta_1, alpha_2, beta_2, percent_lift = 0, min_lift = FALSE) {
    
      alpha_1 <- as.numeric(alpha_1[1])
      beta_1 <- as.numeric(beta_1[1])
      alpha_2 <- as.numeric(alpha_2[1])
      beta_2 <- as.numeric(beta_2[1])
    
      ...
    
    }