Angular and Django – Adding NumPy, Pandas, Matplotlib and Seaborn

In the first post I covered the process of building a simple site with Angular 4 on the client and Django on the server and how to deploy it to heroku. One great benefit to use python is the huge amount of packages it has

Python is great choice for data analysis , it has some popular packages to make development very easy:

  • NumPy – package for creating and using multi-dementional arrays
  • Matplotlib – package for creating graphs
  • Pandas – package for data handling
  • Seaborn – package for data visualization , build on matplotlib

In this post I will cover the process of integrating the above packages on the server side and use it from Angular

Using NumPy

First we need to install it on our virtual environment:

(env) # pip install numpy
(env) # pip freeze > requirements.txt

Then we can add code to use numpy arrays for example – adding new view:

    def getNums(request):
        n = np.array([2, 3, 4])
        name1 = "name-" + str(n[1])
        return HttpResponse('{ "name":"' + name1 + '", "age":31, "city":"New York" }')

Add url to match the view:

    url(r'^getnum/$',views.Customers.getNums),

Run the server and test the result by using the url: 127.0.0.1:8000/getnum

More useful example:

We want to send list of numbers to manipulate it on server – for example calculate average: we build a simple form:

The Angular side:

HTML:

  <input type="text" [(ngModel)]='str1'>
  <button (click)="getavg()">Get Average</button>
  <input type="text" value={{resavg}}>

JavaScript:

 getavg(){
  	this._http.get("/getavg?val=" + this.str1).map(r=>r.text()).subscribe(res => this.resavg= res)
  }

The server side:

    def getAvg(request):
        s1=request.GET.get("val","")
        if len(s1)==0:
            return HttpResponse("none")
        l1=s1.split(',')
        ar=np.array(l1,dtype=int)

        return HttpResponse(str(np.average(ar)))

of course it  is just an example of something you can easily do on the client but if you need something more complex (linear algebra etc.) this is the way

Using Matplotlib

Matplotlib package helps you create many types of graphs. it is based on Numpy Arrays.

Now we want to generate a graph on http request.

The first thing to do is installing matplotlib in our virtual environment:

(env) # pip install matplotlib
(env) # pip freeze > requirements.txt

Then we need to import matplotlib and also add the following command:

import matplotlib as pl
pl.use('Agg')
import matplotlib.pyplot as plt

You need to use a non-interactive backend ‘Agg’ to generate png files

The following code generate graph as a view:

    def getimage(request):
        x = np.arange(0, 2 * np.pi, 0.01)
        s = np.cos(x) ** 2
        plt.plot(x, s)

        plt.xlabel('xlabel(X)')
        plt.ylabel('ylabel(Y)')
        plt.title('Simple Graph!')
        plt.grid(True)

        response = HttpResponse(content_type="image/jpeg")
        plt.savefig(response, format="png")
        return response

Add url for the new view and test it locally:

Load the graph from Angular code:

Add an img tag:

<img src={{imgsrc}} width="500">

Add new data member to the class and connect a button click event:

export class AppComponent {
  ...
  imgsrc='';
  getimage(){
  	this.imgsrc = '/getimg';
  }
  ...


}

Build the angular code and copy to the static folder of your app:

# ng build
# cp dist/*.js ~/projects/hello/helloapp/helloapp/static/

 

Using Pandas

Pandas is a great package for data analysis – one object it defines is a dataframe – a 2 dimension table with many methods act on it like SQL.

We need to install it:

(env) # pip install pandas
(env) # pip freeze > requirements.txt

Now we define a view to return a dataframe in html format:

    def getData(request):
        samp = np.random.randint(100, 600, size=(4, 5))
        df = pd.DataFrame(samp, index=['avi', 'dani', 'rina', 'dina'],
                          columns=['Jan', 'Feb', 'Mar', 'Apr', 'May'])
        return HttpResponse(df.to_html(classes='table table-bordered'))

In the above code we define a numpy array with random numbers, create a DataFrame and convert it to html. The classes we define belongs to bootstrap

Integrate With Angular

We define a span and bind the innerHTML attribute to the pandas table:

<span innerHtml={{pandas}}></span>
...

getDF()
{
   this._http.get("./getdata").map(r => r.text()).subscribe(v => this.pandas = v);
}

 

Using Seaborn

Seaborn helps with creating statistic graphs. It is built on Matplotlib and support some interesting graphs

Install:

(env) # pip install seaborn
(env) # pip freeze > requirements.txt

To use seaborn, we will use a CSV file taken from kaggle.com – Titanic Dataset

To load the file into pandas dataframe  we need to add the file to the project files – we simply put it on the same folder as views.py

module_dir = os.path.dirname(__file__)
file_path = os.path.join(module_dir, 'titanic_train.csv')
df = pd.read_csv(file_path)

we want to see who survived group by sex and Pclass so we generate a factorplot graph:

   def getSBData(request):
        module_dir = os.path.dirname(__file__)
        file_path = os.path.join(module_dir, 'titanic_train.csv')
        df = pd.read_csv(file_path)
        gr=sb.factorplot(x='Survived', hue='Sex', data=df, col='Pclass', kind='count')
        response = HttpResponse(content_type="image/jpeg")
        gr.savefig(response, format="png")
        return response

And Again we declare img tag on Angular, bind it to class member and set it on click

This is the result:

Like the above, we can add any package we want , manipulate it on the server and make an http request from the client to load it.

Final server code(views.py):

from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import TemplateView
import matplotlib as pl
pl.use('Agg')
import pandas as pd
import os
import seaborn as sb


import matplotlib.pyplot as plt
import numpy as np

# Create your views here.
class HomePageView(TemplateView):
    def get(self, request, **kwargs):
        return render(request, 'index.html', context=None)

class LinksPageView(TemplateView):
    def get(self, request, **kwargs):
        return render(request, 'links.html', context=None)


class Customers(TemplateView):
    def getCust(request):
        name='liran'
        return HttpResponse('{ "name":"' + name + '", "age":31, "city":"New York" }')
    def getNums(request):
        n = np.array([2, 3, 4])
        name1 = "name-" + str(n[1])
        return HttpResponse('{ "name":"' + name1 + '", "age":31, "city":"New York" }')

    def getAvg(request):
        s1=request.GET.get("val","")
        if len(s1)==0:
            return HttpResponse("none")
        l1=s1.split(',')
        ar=np.array(l1,dtype=int)

        return HttpResponse(str(np.average(ar)))

    def getimage(request):
        x = np.arange(0, 2 * np.pi, 0.01)
        s = np.cos(x) ** 2
        fig,ax = plt.subplots()
        plt.plot(x, s)

        plt.xlabel('xlabel(X)')
        plt.ylabel('ylabel(Y)')
        plt.title('Simple Graph!')
        plt.grid(True)

        response = HttpResponse(content_type="image/jpeg")
        plt.savefig(response, format="png")
        return response

    def getData(request):
        samp = np.random.randint(100, 600, size=(4, 5))
        df = pd.DataFrame(samp, index=['avi', 'dani', 'rina', 'dina'],
                          columns=['Jan', 'Feb', 'Mar', 'Apr', 'May'])
        return HttpResponse(df.to_html(classes='table table-bordered'))

    def getSBData(request):
        module_dir = os.path.dirname(__file__)
        file_path = os.path.join(module_dir, 'titanic_train.csv')
        df = pd.read_csv(file_path)
        gr=sb.factorplot(x='Survived', hue='Sex', data=df, col='Pclass', kind='count')
        response = HttpResponse(content_type="image/jpeg")
        gr.savefig(response, format="png")
        return response

urls.py

from django.conf.urls import url
from first import views

urlpatterns = [
    url(r'^$', views.HomePageView.as_view()),
    url(r'^links/$' , views.LinksPageView.as_view()),
    url(r'^getcust/$',views.Customers.getCust),
    url(r'^getnum/$',views.Customers.getNums),
    url(r'^getimg/$', views.Customers.getimage),
    url(r'^getdata/$', views.Customers.getData),
    url(r'^getsbdata/$', views.Customers.getSBData),
    url(r'^getavg/$', views.Customers.getAvg),

]

Client side HTML:

<div style="text-align:center">
  <h1>
    Welcome to {{title}}!
  </h1>
  <button (click)="click1()" >click me</button>
  <input type="text" [(ngModel)]='str1'>
  <button (click)="getavg()">Get Average</button>
  <input type="text" value={{resavg}}>
  <button (click)="getimage()">load graph</button>
  <button (click)="getDF()">load table</button>
  <button (click)="getsbimage()">seaborn graph</button>
  <br/>
</div>
<img src={{imgsrc}} width="500">
<h2>Test App: {{c1.name}}</h2>
<span innerHtml={{pandas}}></span>
<img src={{imgsbsrc}} width="1000">

TypeScript

import { Component } from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs';
import 'rxjs/add/operator/map';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor(private _http:Http) {
    this.c1.name = "eli"
   }
  title = 'app';
  imgsrc='';
  pandas='';
  imgsbsrc='';
  str1='';
  resavg='';
  getimage(){
  	this.imgsrc = '/getimg';
  }
  c1:Cust = new Cust();
  click1(){
    this.getAllBooks().subscribe(b => this.c1 = b)

  }
  getavg(){
  	this._http.get("/getavg?val=" + this.str1).map(r=>r.text()).subscribe(res => this.resavg= res)
  }
  getDF(){
    this._http.get("./getdata").map(r => r.text()).subscribe(v => this.pandas = v);  
  }
  getAllBooks()
  {
    return this._http
          .get("./getcust")
          .map(r => <Cust>r.json())

  }
  getsbimage()
  {
  	this.imgsbsrc = '/getsbdata';
  }
}

export class Cust{
    name:string;
    age:number;
    city:string;
}

You can see the final result here

 

 

 

Tagged ,

2 thoughts on “Angular and Django – Adding NumPy, Pandas, Matplotlib and Seaborn

  1. […] For integrating data packages – numpy, spicy, pandas and more see this post […]

  2. […] Integrate with  NumPy, Matplotlib and Pandas […]

Comments are closed.