Graphical user interfaces#
In this notebook we ask bob to create a user interface that allows interacting with a plot.
# load secret API key. You must unpack the contents of api_key.zip
# into the same folder before going ahead.
from dotenv import load_dotenv
load_dotenv()
import os
from bia_bob import bob
bob.initialize(endpoint='https://llm.scads.ai/v1', model='openai/gpt-oss-120b', api_key=os.environ.get('SCADSAI_API_KEY'))
In this example we use a videogame sales dataset by Gregory Smith which is licensed CC-BY 4.0.
%%bob
write python code that
* opens the file vgsales.csv using pandas
* if the file doesn't exist, open it from https://zenodo.org/records/5898311/files/vgsales.csv?download=1
and save it as vgsales.csv
The script loads vgsales.csv with pandas. If the file is not found locally, it downloads it from the provided Zenodo URL, saves it as vgsales.csv, and then reads it.
import urllib.request
import pandas as pd
# 1. Target filename
filename = "vgsales.csv"
# 2‑3. Download if missing
if not os.path.isfile(filename):
url = "https://zenodo.org/records/5898311/files/vgsales.csv?download=1"
urllib.request.urlretrieve(url, filename)
print(f"Downloaded file and saved as '{filename}'.")
# 4. Load into pandas DataFrame
df = pd.read_csv(filename)
# 5. Quick sanity check
print(df.head())
Downloaded file and saved as 'vgsales.csv'.
Rank Name Platform Year Genre Publisher \
0 1 Wii Sports Wii 2006.0 Sports Nintendo
1 2 Super Mario Bros. NES 1985.0 Platform Nintendo
2 3 Mario Kart Wii Wii 2008.0 Racing Nintendo
3 4 Wii Sports Resort Wii 2009.0 Sports Nintendo
4 5 Pokemon Red/Pokemon Blue GB 1996.0 Role-Playing Nintendo
NA_Sales EU_Sales JP_Sales Other_Sales Global_Sales
0 41.49 29.02 3.77 8.46 82.74
1 29.08 3.58 6.81 0.77 40.24
2 15.85 12.88 3.79 3.31 35.82
3 15.75 11.01 3.28 2.96 33.00
4 11.27 8.89 10.22 1.00 31.37
%%bob
Build a graphical user interface using ipywidgets where the user can select the publisher. After the publisher is selected, draw a bar plot showing the NA_Sales, EU_Sales, JP_Sales and Other_Sales.
The bar-plot should be shown right below the pulldown
I will create an interactive UI with ipywidgets that lets the user pick a Publisher from a dropdown. When a publisher is chosen, the code will compute the total NA, EU, JP and Other sales for that publisher and display a bar plot directly under the dropdown.
# --------------------------------------------------------------
# 1. Imports (df is already loaded from the previous step)
# --------------------------------------------------------------
import ipywidgets as widgets
import matplotlib.pyplot as plt
from IPython.display import display
# --------------------------------------------------------------
# 2. Create the publisher dropdown
# --------------------------------------------------------------
publishers = sorted(df['Publisher'].dropna().unique())
publisher_dropdown = widgets.Dropdown(
options=publishers,
description='Publisher:',
value=publishers[0],
style={'description_width': 'initial'}
)
# --------------------------------------------------------------
# 3. Output widget for the bar plot
# --------------------------------------------------------------
plot_out = widgets.Output()
# --------------------------------------------------------------
# 4. Callback to update the plot when a publisher is selected
# --------------------------------------------------------------
def update_plot(change):
# Only act on value changes (ignore initial creation)
if change['type'] != 'change' or change['name'] != 'value':
return
selected_pub = change['new']
# Filter rows for the selected publisher
sub = df[df['Publisher'] == selected_pub]
# Sum sales per region
sales = {
'NA_Sales' : sub['NA_Sales'].sum(),
'EU_Sales' : sub['EU_Sales'].sum(),
'JP_Sales' : sub['JP_Sales'].sum(),
'Other_Sales' : sub['Other_Sales'].sum()
}
# Plot
with plot_out:
plot_out.clear_output(wait=True) # clear previous figure
fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(sales.keys(), sales.values(),
color=['steelblue', 'orange', 'green', 'purple'])
ax.set_ylabel('Total Sales (million units)')
ax.set_title(f'Total Sales for Publisher: {selected_pub}')
plt.tight_layout()
plt.show()
# --------------------------------------------------------------
# 5. Link the callback and display the UI
# --------------------------------------------------------------
publisher_dropdown.observe(update_plot, names='value')
# Show widgets (dropdown on top, plot below)
display(widgets.VBox([publisher_dropdown, plot_out]))
# Trigger initial plot for the default selection
update_plot({'type': 'change', 'name': 'value', 'new': publisher_dropdown.value})
Exercise#
Extend the user interface above by an additional pulldown for selecting which column should serve as hue for the visualization of the data points.