Exerciseschevron_rightChapter 5chevron_right5.7
fitness_center

Exercise 5.7

Production Ranking Bar Chart

Level 2
Chapter 5: Data Visualization & Plotting
descriptionProblem

Build a horizontal bar chart ranking the top 10 wells in a 12-well field by current oil rate. Horizontal bars beat vertical when well names get long; labels never collide.

The starter provides a DataFrame wells with well and oil_bopd.

Required:

  1. Sort by oil_bopd descending and take the top 10 into a new

DataFrame top10.

  1. Plot horizontal bars (ax.barh).
  2. Color each bar based on water cut: green for water_cut < 0.50,

amber for 0.50–0.75, red for > 0.75.

  1. Invert the y-axis so the highest-rate well sits at the top of

the chart.

  1. Add x-label, title, and value labels on the right side of each bar

(e.g. "1,842 bopd").

lightbulbHints (0/4)

Stuck? Reveal hints one at a time — they progress from nudge to near-solution.

codeYour solution
main.py
visibilityReveal reference solutionexpand_more

Try solving it yourself first — the hints walk you through it. The solution below is one valid approach; yours may differ and still be correct.

import pandas as pd
import matplotlib.pyplot as plt

wells = pd.DataFrame({
    "well":      ["OD-001","OD-002","OD-003","OD-004","OD-005","OD-006",
                  "OD-007","OD-008","OD-009","OD-010","OD-011","OD-012"],
    "oil_bopd":  [1842, 320, 1155, 620, 2210, 85, 2950, 410, 1520, 780, 1090, 240],
    "water_cut": [0.42, 0.88, 0.56, 0.71, 0.22, 0.92, 0.08, 0.65, 0.34, 0.78, 0.45, 0.83],
})

top10 = wells.sort_values("oil_bopd", ascending=False).head(10).reset_index(drop=True)


def color_for(wc):
    if wc > 0.75: return "#CC4444"
    if wc > 0.50: return "#D4A847"
    return "#2E8B57"


colors = [color_for(wc) for wc in top10["water_cut"]]

fig, ax = plt.subplots(figsize=(8, 6))
bars = ax.barh(top10["well"], top10["oil_bopd"], color=colors)
ax.invert_yaxis()
ax.set_xlabel("Oil rate (bopd)")
ax.set_title("Top 10 wells - current oil rate (colored by water cut)")
ax.grid(axis="x", alpha=0.25)

for bar, rate in zip(bars, top10["oil_bopd"]):
    ax.text(bar.get_width() + 30, bar.get_y() + bar.get_height() / 2,
            f"{rate:,} bopd", va="center", fontsize=9)

plt.tight_layout()
plt.show()

lockCopying code is a Full Access feature.