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.
Apparently rpy2 does not provide a direct function which can return a file object to python. So what i recommend is:
On your settings.py define a variable where your R scripts/images should be saved
STATIC_R = 'r_plots'
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',)
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>
For this you can use the interface between R and Python given in the RPy2` python package . This allows you to run a R session alongside a python session, and being able to run R commands from within python and getting back the result.
Alternatively, you can run R as a commandline script on the server, have a look at Rscript
to get this working. This script could produce a png based on a number of input arguments. Python could then pick up the png and send it back to the user.
As a third alternative, you could run R via Rserve
, and create a connection to it to get the plotting done. For example see here .
Solution 3 is a bit overkill, but allows you to use R on a different server than your Django instance. Solution 1. is quite flexible, but more complex. Finally, solution 2. is the simplest solution, but sometimes lacks flexibility, especially if lot's of interaction between R and Python is needed.
If you install.package('magick')
in your R instance then you can use rpy2
to get the image data back to Python as follows (I've used a simplier plot function):
from io import BytesIO
import PIL.Image as Image
import rpy2.robjects as ro
def main():
r = ro.r
r('''
library("magick")
figure <- image_graph(width = 400, height = 400, res = 96)
plot(c(1,2,3))
image <- image_write(figure, path = NULL, format = "png")
''')
image_data = ro.globalenv['image']
image = Image.open(BytesIO(bytes(image_data)))
return image
if __name__ == '__main__':
image = main()
image.show()
You can then use the method here to render the image within a Django template.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.