Integration between R and languages ​​for web interface / systems


#1

Good Afternoon.

I would like to know, please, if anyone has already done any kind of integration between languages ​​for web interface / system development and R.
I have an application made in shiny developed as a prototype and stored on the shiny server, but I would like to migrate it / develop it in Java, for example, and call R codes for statistical analyzes, graphs, maps, etc. What is your experience about it? Thank you in advance!

PS: I am a statistician and I work with R. I gave the Java example, but I do not know if it would be the most appropriate language to do this.


#2

You might look into the plumber package, which allows easy creation of a REST API simply by tagging your code with nicely formatted comments (much like roxygen2). It essentially allows a web-app to call an R function via a REST API call and so is a nice fit for statistical analyses, etc.

As for the serving of graphs, maps, etc., that might be something that you serve as a shiny object / widget / etc. and then embed in the Java app via an iframe. I cannot imagine a way to serve graphs / maps / etc. via an API unless it’s a static image, and even then, I’m not sure that a Plumber API would be the proper fit for serving those images. I guess it would theoretically be possible by delivering a base64 encoded string… but that just seems wrong. You could always deliver a network address / URL as well if the image is accessible to both applications. See the base64enc package for more exploration. Interesting question!


#3

Hello, @cole. Thank you so much for your answer.

I’ve been researching about creating REST API’s. I found the plumber package and opencpu package with the help of colleagues from a Facebook community.

According to my research, I realized that opencpu is more appropriate because it is more general and presents several ways to solve security and scalability problems. While the plumber is simpler.

In this way, I decided to create a REST API using the opencpu package, which basically requires the creation of an R package and the use of the opencpu :: ocpu_start_app (‘package’) function to run the API.

So I created an R package consisting of two basic content functions that are in my current shiny application. The first makes a filter in the database according to parameters, which worked perfectly when doing POST request using the ‘curl’ function in the terminal; and the second refers to a histogram created in the highcharter package, as function below.

function (data = lic, ano = ano, valor_max = valor, dir = “.”)

{
require(tidyr)
valor_graf <- filter_data_ano(data = data, ano = ano)
valor_graf <- dplyr::filter(valor_graf, valor <= valor_max)

if (nrow(valor_graf) != 0) {
    hc <- highcharter::hchart(hist(valor_graf$valor, plot = FALSE), 
        color = "#bcbddc", name = FALSE) %>% highcharter::hc_xAxis(title = list(text = "Valor")) %>% 
        highcharter::hc_yAxis(title = list(text = "Quantidade")) %>% 
        highcharter::hc_legend(enabled = FALSE) 

    htmlwidgets::saveWidget(hc, paste(dir, "/valor_graf.html", sep = ""), selfcontained = FALSE)

}

else {

    hc <- highcharter::highchart() %>% highcharter::hc_chart(marginTop = 80, 
        marginBottom = 50) %>% highcharter::hc_add_series(data = c(NA, 
        NA), showInLegend = F) %>% highcharter::hc_xAxis(min = 1, 
        max = 50) %>% highcharter::hc_yAxis(min = 1, max = 50)

    htmlwidgets::saveWidget(hc, paste(dir, "/valor_graf.html", 
        sep = ""), selfcontained = FALSE)
}

}

Regarding the creation of this graphic, note that I had to use the htmlwidgets :: saveWidget () function to save the graphic in html extension, since it is dynamic. I was able to make a POST request using the ‘curl’ function on the terminal. The ‘graph.html’ file has been placed in a temporary API folder.

Also, through internet searches, I realized that for maps created in the leaflet package, for example, I should also use the htmlwidgets :: saveWidget () function to save it in .html.

I say this because you mentioned that it would be more complicated to use the API for graphs and interactive maps. So, according to my report above, do you think the API via opencpu is inappropriate for this, ie create a .html file with interactive charts and maps? I’ve been able to do it, but I do not know how easy it will be to use it when you apply through another language.

Thank you!


#4

@pjsdcrosa Very interesting approach! I am unfamiliar with the opencpu package, but will have to check it out! Very clever approach to using the htmlwidgets::saveWidget() function, as well, I presume into a self-contained HTML file? I have never explored this approach, per se, but am quite interested in doing so now!

Regarding the difficulty for serving graphs / interactive maps I referenced, it depends on what kind of interactivity you are looking for. If you are looking for interactivity that is served in a static HTML file (via HTML / JS stuff), then hopefully your static HTML (saveWidget) approach should work fine. The only trick is how you get the parent application to acquire / render the HTML - perhaps it would be possible to provide the HTML back to the parent application as the response to the API call, but hopefully that would not require writing to disk and then reading from disk. Maybe there would be some way to send the HTML directly, thinking about the response as the “saveWidget” operation. Latency would be the concern here, as well as any weirdness getting the parent to render the HTML appropriately inside its current page. Also, refreshes of the page / changes to the API call would probably not be cached appropriately and might require a full re-render? That might be a concern if the HTML files are large / have lots of JavaScript in them. I’m just thinking out loud here :slight_smile:

However, if you are looking for the level of interactivity that Shiny applications generally provide (i.e. has a server back-end, can get new data, filter data, etc.), that is where you would need an iframe displaying the Shiny app / widget. As a static HTML file, you can have the “interactivity” of JavaScript, but you will not have a “dynamic” webapp that alters its display on user input. iframe is the way that Shiny / reactive widgets are canonically embedded in a parent application and you can see an example here (at the bottom of the page).


#5

Just doing some follow-up reading on this. There are some very interesting examples out on the opencpu page. In particular, this leaflet app (view here) seems to be very much like what you are shooting for.

They create the map with saveWidget (note that dependencies are saved externally… so more would probably have to move than just the HTML):

htmlwidgets::saveWidget(m, "mymap.html", selfcontained = FALSE)

And then show the generated HTML file in an iframe:

$("iframe").attr('src', session.getFileURL("mymap.html"));

I imagine there could be other ways to deliver the HTML file. I am curious about the approaches I mentioned above - if it would be possible to save a self-contained HTML and then return the HTML to the client without writing to disk first.