Data Visualization: Coding a Dash Application on Brazil’s Population and GDP
By: Murilo Bento
Tags: Plotly Express, Pandas, Data Science, Plotly, Python

Data Visualization: Coding a Dash Application on Brazil’s Population and GDP

A simple application written in Python, using Pandas and Plotly, that aims to provide good visualization on Brazil’s population and GDP using an interactive map and bar graph. Murilo Bento Nov 24, 2020·5 min read

Photo by sergio souza on Unsplash

Brazil is a wonderful country to visit and to live in. However, the first words that comes to my mind when it comes to the country, are Christ the Redeemer, the statue, the Copacabana Beach and the Carnival. Although those are pretty popular, they only represent a small set of information about the country. What about the other states? How many people live in those other areas? How much is their GDP in comparison to other regions of Brazil?

In this article, we are going to investigate the use of Python, Pandas and the Dash library in order to not only answer those questions, but present them in an interactive way.

The Data

The dataset used for this project is available at Kaggle, that is Gabriel Rios’ Economy and Population of Cities in Brazil (IBGE), that was extracted from the Brazilian Institute of Geography and Statistics (IBGE).

Data Acquisition and Refinement

This project uses Pandas, NumPy, and Plotly.

Imports

import dash

import dash_core_components as dcc

import dash_html_components as html

from dash.dependencies import Input, Output

import plotly.express as px

import numpy as np

import pandas as pd

import math

Reading the Dataset into a Pandas DataFrame

df = pd.read_excel('input/Cities_Brazil_IBGE.xlsx')

df.head()

Fixing an issue with the latitude and longitude

There is a problem here: The latitude and longitude fields are not correct, as the fields are not correctly inserted/read. For example, a latitude of -9.90571 will be represented as -990571 in the DataFrame. So, before using the data, we need to fix them first by creating and applying functions to the elements of the Longitude and Latitude columns.

def fix_lat(line):

element = line['Latitude']

region = line['RegiaoBrasil'] if ',' in str(element):

return float(str(element).replace(',', '.')) result = element / (10**(int(math.log10(abs(element)))-1)) if region == 'N' or region == 'NE':

if abs(result) > 18:

result = result / 10

return result if abs(result) > 35.0:

result = result / 10

return result def fix_lon(element):

if ',' in str(element):

return float(str(element).replace(',', '.'))

return element / (10**(int(math.log10(abs(element)))-1))

Although this does not provide a complete correctness to the real data, it allows to plot the map. Now that our helper functions are defined, we just need to apply them to the elements.

df['Latitude'] = pd.to_numeric(df.apply(fix_lat, axis=1))

df['Longitude'] = pd.to_numeric(df['Longitude'].apply(fix_lon))

df['Pib_2014'] = pd.to_numeric(df['Pib_2014'].apply(lambda element: float(str(element).replace(',', '.'))))

Creating the Plots

Now that we have our data fixed, we are going to create two plots: A scatter plot for the population and a bar graph to represent the mean of the GPD of every region of Brazil.

def plot_scatter(dataframe):

scatter = px.scatter_mapbox(dataframe,

lat='Latitude',

lon='Longitude',

text="LocalCidade",

zoom=3,

size='PopEstimada_2018',

mapbox_style='carto-positron')

scatter.update_layout(margin={'r':0,'t':0,'l':0,'b':0})

return scatter scatter = plot_scatter(df)

We created the scatter plot using the Latitude and Longitude columns of the dataframe. Now, we are going to create the bar graph of the GPD.

pib_per_region = df[['RegiaoBrasil', 'Pib_2014']].groupby(['RegiaoBrasil'])['Pib_2014'].mean() bar = px.bar(pib_per_region,

x=pib_per_region.index,

y="Pib_2014",

text="Pib_2014",

labels={'x':'Região'},

color=np.arange(0, 5, 1).tolist(),

color_continuous_scale=px.colors.sequential.Viridis_r,

barmode="overlay",

opacity=1,

title="PIB Médio das Regiões do Brasil") bar.update_layout(

title_font_size=20,

titlefont=dict(color='black'))

bar.update_layout(uniformtext_minsize=8, uniformtext_mode='hide')

bar.update_yaxes(title="PIB Médio", titlefont=dict(color='black'), tickfont=dict(color='black'))

bar.update_xaxes(titlefont=dict(color='black'), tickfont=dict(color='black')) bar.update_layout(coloraxis_showscale=False)

Here, we grouped the regions and selected the mean of the GPD of them.

Building the Dash

Now that we have our plots ready, we are going to create the Dash App. The first step is to instantiate a Dash object, specifying an optional external stylesheet.

Now that the Dash object is instantiated, we proceed to build the HTML layout of our dash application.

app.layout = html.Div([

html.H1("Dados Demográficos do Brasil", style={'text-align':'center', 'color':'black'}), dcc.Graph(

id='population-scatter',

figure=scatter

),

dcc.Dropdown(

id='bar-selector',

options=[

{'label': 'Nordeste', 'value': 'NE'},

{'label': 'Norte', 'value': 'N'},

{'label': 'Centro Oeste', 'value': 'CO'},

{'label': 'Sudeste', 'value': 'SE'},

{'label': 'Sul', 'value': 'SUL'}

],

placeholder="Região",

style={'width':"40%"}

),

dcc.Graph(

id='pib-bar',

figure=bar),

])

Notice that there’s a dropdown specified there, with five options (Nordeste, Norte, Centro Oeste, Sudeste and Sul). We want to filter the displaying data according to the option the user has selected.



[Input(component_id='bar-selector', component_property='value')])

def update(region):

if region is None:

return plot_scatter(df) @app .callback(Output(component_id='population-scatter', component_property='figure'),[Input(component_id='bar-selector', component_property='value')])def update(region):if region is None:return plot_scatter(df) update_scatter = df.copy()

update_scatter = update_scatter[update_scatter.RegiaoBrasil == region] return plot_scatter(update_scatter)

Now that everything is ready, we just need to define the main function.

if __name__ == '__main__':

app.run_server(debug=True, use_reloader=False)

Result

Once we run the script we created, a local server is created. This is the result: