Exerciseschevron_rightChapter 5chevron_right5.8
fitness_center

Exercise 5.8

Field Bubble Map

Level 2
Chapter 5: Data Visualization & Plotting
descriptionProblem

A bubble map is the fastest way to spot spatial patterns across a field: high-water-cut wells clustering on one side, the field's biggest producers concentrated near a structural high, etc.

The starter has 10 wells with lat, lon, oil_bopd, and water_cut.

Build the map:

  1. ax.scatter(lon, lat, ...). Pass two visual encodings:
  • s = oil_bopd / 5: bubble size proportional to current rate
  • c = water_cut, cmap="RdYlGn_r": colour by water cut

(green = low, red = high; the _r reverses the default).

  1. Add a colour bar with label "Water cut" (fig.colorbar(...)).
  2. Annotate each well with its name (ax.annotate(name, (lon, lat), ...)).
  3. Axis labels ("Longitude", "Latitude"), title, light grid.
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

field = pd.DataFrame({
    "well":      ["OD-001","OD-002","OD-003","OD-004","OD-005",
                  "OD-006","OD-007","OD-008","OD-009","OD-010"],
    "lon":       [7.005, 7.012, 7.008, 7.018, 7.001,
                  7.022, 6.998, 7.015, 7.010, 7.020],
    "lat":       [4.770, 4.775, 4.768, 4.778, 4.772,
                  4.780, 4.766, 4.776, 4.770, 4.782],
    "oil_bopd":  [1842, 320, 1155, 620, 2210, 85, 2950, 410, 1520, 780],
    "water_cut": [0.42, 0.88, 0.56, 0.71, 0.22, 0.92, 0.08, 0.65, 0.34, 0.78],
})

fig, ax = plt.subplots(figsize=(8, 6))
sc = ax.scatter(
    field["lon"], field["lat"],
    s=field["oil_bopd"] / 5,
    c=field["water_cut"],
    cmap="RdYlGn_r",
    alpha=0.8, edgecolors="black", linewidths=0.7,
)
cbar = fig.colorbar(sc, ax=ax)
cbar.set_label("Water cut")

for _, row in field.iterrows():
    ax.annotate(row["well"], (row["lon"], row["lat"]),
                xytext=(6, 6), textcoords="offset points",
                fontsize=8, color="#333")

ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")
ax.set_title("OML 58 - current oil rate (size) and water cut (color)")
ax.grid(True, alpha=0.25)
plt.tight_layout()
plt.show()

lockCopying code is a Full Access feature.