Day 4 — Solutions

pandas and APIs

import pandas as pd
nes = pd.read_csv("nes2020_subset.csv")

Exercise 1 — Inspecting a DataFrame

print(nes.head())
print(nes.columns.tolist())
print(nes.shape)        # (rows, columns)
print(nes.describe())

shape is a tuple, describe() gives count/mean/std/min/quartiles/max for each numeric column.


Exercise 2 — Filtering

high_biden = nes[nes["ft_biden"] > 80]
print(len(high_biden))
print(high_biden["ft_trump"].mean())

Boolean indexing: nes["ft_biden"] > 80 returns a Series of True/False, and nes[...] keeps the rows where it’s True. .mean() on the filtered ft_trump column gives you the conditional average.


Exercise 3 — Summary by group

result = nes.groupby("freetrade")["ft_police"].mean()
print(result)

groupby splits the data into chunks based on the column you pass, and .mean() summarizes each chunk. Selecting ["ft_police"] before .mean() keeps only that column in the result.


Exercise 4 — Creating a new column

nes["biden_minus_trump"] = nes["ft_biden"] - nes["ft_trump"]
print(nes["biden_minus_trump"].mean())
print((nes["biden_minus_trump"] > 0).sum())

Subtracting two Series produces a new Series, pandas handles the row alignment for you. (series > 0).sum() counts True values (because True acts like 1 in arithmetic).


Exercise 5 — A small DataFrame from scratch

import pandas as pd

data = {
    "policy": ["education", "healthcare", "defense", "infrastructure", "climate"],
    "budget_b": [82, 1670, 850, 244, 75],
    "approve_pct": [68, 54, 49, 71, 62],
}

df = pd.DataFrame(data)

# 1. Sort by budget descending
print(df.sort_values("budget_b", ascending=False))

# 2. Filter to high approval
print(df[df["approve_pct"] > 60])

# 3. Mean approval
print(df["approve_pct"].mean())
           policy  budget_b  approve_pct
1      healthcare      1670           54
2         defense       850           49
3  infrastructure       244           71
0       education        82           68
4         climate        75           62
           policy  budget_b  approve_pct
0       education        82           68
3  infrastructure       244           71
4         climate        75           62
60.8

sort_values doesn’t mutate the DataFrame — it returns a new sorted view (use inplace=True if you want to overwrite).


Exercise 6 — Hitting an API

import requests

url = "https://api.census.gov/data/2020/dec/pl?get=NAME,P1_001N&for=state:*"
r = requests.get(url)

print(r.status_code)        # should be 200

data = r.json()
print(data[:5])

The Census API returns a list of lists — first row is headers (["NAME", "P1_001N", "state"]), each subsequent row is one state.


Exercise 7 — Putting it together: API → DataFrame

import requests
import pandas as pd

url = "https://api.census.gov/data/2020/dec/pl?get=NAME,P1_001N&for=state:*"
r = requests.get(url)
data = r.json()

# First row is column names; rest are data
df = pd.DataFrame(data[1:], columns=data[0])

# Convert population column to integer
df["P1_001N"] = df["P1_001N"].astype(int)

# Sort and print top 10
top10 = df.sort_values("P1_001N", ascending=False).head(10)
print(top10[["NAME", "P1_001N"]])

pd.DataFrame(data[1:], columns=data[0]) builds a DataFrame from the rows (excluding the header) and assigns the header as column names. The Census API returns numeric values as strings, so .astype(int) converts them so sorting and arithmetic work correctly.