Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use R in Python to return an R graph through Django?

Tags:

python

r

django

I'm trying to run the following R code through my Django application with the end result being a printed R graph in a Python Django webpage. Here is the code for R.

t=read.table(file=file("request.FILES['fileUpload']"))
colnames(t) <- c('x', 'y')
t = data.frame(t)
fit1 = lm(y ~ x, data = t)
par(mfrow=c(1,1))
plot(x=t$x, y=t$y, xlab="x", ylab="y", main="Simple Linear Regression", xlim=c(0,100), ylim=c(0,6), par=20)
abline(fit1, col="red")

Here is something like what I am trying to achieve in the Django function.

from django.shortcuts import render, HttpResponse
import pandas as pd

def upload_files(request):
    if request.method == 'POST':
        upload = pd.read_table(request.FILES['fileUpload'])
        << Run R Code Here and return the graph >>
        response = RGraph
        return response
             OR
        return render(request, 'Regression/index.html', {'graph':response})
    return render(request, 'Regression/index.html')

HTML code is as follows.

<html>
    <title>Import File</title>
        <body>
            <h1>Import File</h1>
                <hr>
            {% if graph %}
                <img alt="my base64 graph" src="data:image/png;base64,{{graph}}" />
            {% endif %}
            <form enctype="multipart/form-data" method="post">
                {% csrf_token %}
                <input type="file" name="fileUpload" />
                <input type="submit" value="Submit" />
            </form>
        </body>
</html>

As always, thanks for the help.

like image 886
Ravaal Avatar asked Sep 21 '15 14:09

Ravaal


People also ask

Can Python call an R script?

Using R and Python together at the same time is incredibly easy if you already have your R scripts prepared. Calling them from Python boils down to a single line of code.

What does R mean in Django?

It means to treat this string as a literal. Often times you see characters like '\' that need to be escaped, the use of 'r' prevents that from needing to be explicitly written. Follow this answer to receive notifications.


1 Answers

Apparently rpy2 does not provide a direct function which can return a file object to python. So what i recommend is:

1) Set a path to save your R image files

  • On your settings.py define a variable where your R scripts/images should be saved

    STATIC_R = 'r_plots'
    

2) Build a model/form to handle the file management based on your settings

  • Model

    from django.conf import settings
    
    class RScript(models.Model):
        script = FileField(upload_to=settings.STATIC_R)
    
        @property
        def script_path(self):
            return os.path.basename(self.script.name)
    
  • Remember (from docs): FielField.upload_to: A local filesystem path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute.

  • Form

    class RScriptForm(forms.ModelForm):
        class Metal:
            model = RScript
            fields = ('script',)
    

3) Running you code from upload

  • Receive your R script and save it

    my_plot_script = '''
        t=read.table(file=file("{path}"))
        colnames(t) <- c('x', 'y')
        t = data.frame(t)
        fit1 = lm(y ~ x, data = t)
        par(mfrow=c(1,1))
        png(filename="{path}.png")
        plot = plot(x=t$x, y=t$y, xlab="x", ylab="y", main="Simple Linear Regression", xlim=c(0,100), ylim=c(0,6), par=20)
        abline(fit1, col="red")
        dev.off()
    '''
    
    def my_view(request):
        if request.method == 'POST':
            form = RScriptForm(request.POST)
            if form.is_valid():
                form.save()
                (...)
    
  • Now that we have script saved let's try to running it with rpy2

    my_plot_script = '''
        t=read.table(file=file("{path}"))
        colnames(t) <- c('x', 'y')
        t = data.frame(t)
        fit1 = lm(y ~ x, data = t)
        par(mfrow=c(1,1))
        png(filename="{path}.png")
        plot = plot(x=t$x, y=t$y, xlab="x", ylab="y", main="Simple Linear Regression", xlim=c(0,100), ylim=c(0,6), par=20)
        abline(fit1, col="red")
        dev.off()
    '''
    
    def my_view(request):
        context = {}
        if request.method == 'POST':
            form = RScriptForm(request.POST)
            if form.is_valid():
                form.save()
                import rpy2.robjects as robjects
                robjects.r(my_plot_script.format(form.instance.script_path))
                context['graph'] = form.instance.script_path + '.png'
                return render(request, 'Regression/graph.html', context)
    
  • on your template

    <html>
        <title>Import File</title>
            <body>
                <h1>Import File</h1>
                    <hr>
                {% if graph %}
                    <img alt="my base64 graph" src="{{graph}}" />
                {% endif %}
                <form enctype="multipart/form-data" method="post">
                    {% csrf_token %}
                    <input type="file" name="fileUpload" />
                    <input type="submit" value="Submit" />
                </form>
            </body>
    </html>
    
like image 119
Ramon Moraes Avatar answered Oct 30 '22 03:10

Ramon Moraes