Tkinter-based backend 

Let's try to copy the following code to a separate text file and name it chapter6_gui.py. After that, type python chapter6_gui.py in your terminal (Mac/Linux) or Command Prompt (Windows). If you are unsure about how to open a terminal or Command Prompt, refer to Chapter 6, Hello Plotting World!, for more details:

import matplotlib
import matplotlib.pyplot as plt
import textwrap # Standard library for text wraping
import requests
import pandas as pd
from bs4 import BeautifulSoup


# Specify the url
url = "https://www.bls.gov/emp/ep_table_001.htm"

# Query the website and get the html response
response = requests.get(url)

# Parse the returned html using BeautifulSoup
bs = BeautifulSoup(response.text)

# Select the table header by CSS selector
thead = bs.select("#bodytext > table > thead")[0]

# Select the table body by CSS selector
tbody = bs.select("#bodytext > table > tbody")[0]

# Get the column names
headers = []

# Find all header columns in <thead> as specified by <th> html tags
for col in thead.find_all('th'):
headers.append(col.text.strip())

# Dictionary of lists for storing parsed data
data = {header:[] for header in headers}

# Parse the rows in table body
for row in tbody.find_all('tr'):
# Find all columns in a row as specified by <th> or <td> html tags
cols = row.find_all(['th','td'])

# enumerate() allows us to loop over an iterable,
# and return each item preceded by a counter
for i, col in enumerate(cols):
# Strip white space around the text
value = col.text.strip()

# Try to convert the columns to float, except the first column
if i > 0:
value = float(value.replace(',','')) # Remove all commas in
# string

# Append the float number to the dict of lists
data[headers[i]].append(value)

# Create a dataframe from the parsed dictionary
df = pd.DataFrame(data)

# Create a figure
fig, ax = plt.subplots(figsize=(6,7))

# Create a list of x ticks positions
ind = range(df.shape[0])

# Plot a bar chart of median usual weekly earnings by educational
# attainments
rects = ax.barh(ind, df["Median usual weekly earnings ($)"], height=0.5)

# Set the x-axis label
ax.set_xlabel('Median weekly earnings (USD)')

# Label the x ticks
# The tick labels are a bit too long, let's wrap them in 15-char lines
ylabels=[textwrap.fill(label,15) for label in df["Educational attainment"]]
ax.set_yticks(ind)
ax.set_yticklabels(ylabels)

# Give extra margin at the bottom to display the tick labels
fig.subplots_adjust(left=0.3)

# Show the figure in a GUI
plt.show()

We see a pop-up window similar to the following. We can pan, zoom to selection, configure subplot margins, save, and go back and forth between different views by clicking on the buttons on the bottom toolbar. If we put our mouse over the plot, we can also observe the exact coordinates in the bottom-right corner. This feature is extremely useful for dissecting data points that are close to each other.

Next, we are going to extend the application by adding a radio button widget on top of the figure, such that we can switch between the display of weekly earnings or unemployment rates. The radio button can be found in matplotlib.widgets, and we are going to attach a data updating function to the .on_clicked() event of the button. You can paste the following code right before the plt.show() line in the previous code example (chapter6_gui.py). Let's see how it works:

# Import Matplotlib radio button widget
from matplotlib.widgets import RadioButtons

# Create axes for holding the radio selectors.
# supply [left, bottom, width, height] in normalized (0, 1) units
bax = plt.axes([0.3, 0.9, 0.4, 0.1])
radio = RadioButtons(bax, ('Weekly earnings', 'Unemployment rate'))

# Define the function for updating the displayed values
# when the radio button is clicked
def radiofunc(label):
# Select columns from dataframe, and change axis label depending on
# selection
if label == 'Weekly earnings':
data = df["Median usual weekly earnings ($)"]
ax.set_xlabel('Median weekly earnings (USD)')
elif label == 'Unemployment rate':
data = df["Unemployment rate (%)"]
ax.set_xlabel('Unemployment rate (%)')

# Update the bar heights
for i, rect in enumerate(rects):
rect.set_width(data[i])

# Rescale the x-axis range
ax.set_xlim(xmin=0, xmax=data.max()*1.1)

# Redraw the figure
plt.draw()

# Attach radiofunc to the on_clicked event of the radio button
radio.on_clicked(radiofunc)

You will be welcomed by a new radio selector box at the top of the figure. Try switching between the two states and see if the figure is updated accordingly. The complete code is also available as chapter6_tkinter.py in our code repository.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset