Home > Back-end >  Data Visualisation in Python-Flask using csv file
Data Visualisation in Python-Flask using csv file

Time:12-29

I want to create a Python Flask website, in which one webpage shows the bar-chart, another shows the line-chart and lastly the third page shows the timeline. I have got a csv file with Year, Exports and Imports:

1952,8645,8284
1953,9472,8186
1954,11266,9887
1955,13149,12512
1956,15779,14298

Then I have used a datas.py file, which will read the csv and show the csv table in webpage

from flask import Blueprint, current_app, render_template
import os
import csv

datas = Blueprint('datas', __name__)


def read_csv():
    data = []
    path = os.path.join(
        current_app.root_path, os.pardir,
        'scraping', 'exports-imports.csv'
    )
    try:
        with open(path, 'r') as f:
            reader = csv.reader(f)
            for row in reader:
                data.append(row)
    except FileNotFoundError:
        return "Error: CSV file was not found"
    return data


@datas.route('/datas')
def show_data():
    try:
        data = read_csv()
        return render_template('datas.html', data=data)
    except IOError:
        return "The file doesn't exist"

I want to use the function read_csv() and plot the graphs in the page.

from flask import Blueprint, render_template
import matplotlib.pyplot as plt
from .datas import read_csv

graphs = Blueprint('graphs', __name__)


@graphs.route('/line-chart')
def show_line_chart():
    data = read_csv()

    years = [row[0] for row in data]
    exports = [row[1] for row in data]
    imports = [row[2] for row in data]

    plt.plot(years, exports, label="Exports")
    plt.plot(years, imports, label="Imports")
    plt.xlabel('Year')
    plt.ylabel('Value')
    plt.title('Foreign Trade')
    plt.legend()
    plt.tight_layout()
    plt.savefig('static/line-chart.png')

    return render_template('line-chart.html')

Lastly line-chart.html:

{% extends "base.html" %}
{% block title %}Line Chart{% endblock %}
{% block content %}
<div >
    <h1 >Foreign Trade</h1>
    <img src="{{ url_for('static', filename='line-chart.png') }}" alt="Line Chart">
</div>
{% endblock %}

The problem is that it is not creating any img file in the project. Is there any way to build up the image or any other way to solve the problem?

CodePudding user response:

The save image error is mostly due to an error on the path you are given to plt.savefig() function. Remember that matplot lib doesnt live relative to your app folder. So try given the entire path maybe something like app/static/filename.jpg

Other way of implementing Charts on a flask app is via JavaScript with Libraries like ChartJS or Google Charts.

I'been working on a flask extensions that makes ChartJS integration easy. You could give it a try its in a really early stage tho but suits your problem really well.

You could follow the instructions and repository Here

CodePudding user response:

Finally was able to solve the problem.

    import matplotlib.pyplot as plt
    import numpy as np
    from io import BytesIO
    from flask import Blueprint, send_file
    from website.datas import read_csv

    graphs = Blueprint('graphs', __name__)
    
    
    @graphs.route('/line-chart')
    def show_line_chart():
        data = read_csv()

    years = [int(row[0]) for row in data]
    exports = [int(row[1]) for row in data]
    imports = [int(row[2]) for row in data]

    fig, ax = plt.subplots()

    ax.plot(years, exports, label='Exports')
    ax.plot(years, imports, label='Imports')

    ax.set_xlabel('Year')
    ax.set_ylabel('Value (USD)')
    ax.set_title('Foreign Trade')
    ax.legend()

    buf = BytesIO()
    plt.savefig(buf, format='png')
    buf.seek(0)
    return send_file(buf, mimetype='image/png')

And the HTML file looks like this:

{% extends "base.html" %}
{% block title %}Line Chart{% endblock %}
{% block content %}
<div >
    <h1 >Foreign Trade</h1>
    <img src="/line-chart" alt="Line Chart">
</div>
{% endblock %}

It will create an image in the flask, but it is not hoverable, which needs to be solved.

  • Related