marimo-team/marimo-learn
3
1# /// script2# requires-python = ">=3.10"3# dependencies = [4# "marimo",5# "matplotlib==3.10.8",6# "matplotlib-venn==1.1.2",7# "numpy==2.4.3",8# ]9# ///10 11import marimo12 13__generated_with = "0.18.4"14app = marimo.App(width="medium", app_title="Conditional Probability")15 16 17@app.cell18def _():19 import marimo as mo20 return (mo,)21 22 23@app.cell(hide_code=True)24def _(mo):25 mo.md(r"""26 # Conditional Probability27 28 _This notebook is a computational companion to the book ["Probability for Computer Scientists"](https://chrispiech.github.io/probabilityForComputerScientists/en/part1/cond_prob/), by Stanford professor Chris Piech._29 30 In probability theory, we often want to update our beliefs when we receive new information.31 Conditional probability helps us formalize this process by calculating "_what is the chance of32 event $E$ happening given that we have already observed some other event $F$?_"[<sup>1</sup>](https://chrispiech.github.io/probabilityForComputerScientists/en/part1/cond_prob/)33 34 When we condition on an event $F$:35 36 - We enter the universe where $F$ has occurred37 - Only outcomes consistent with $F$ are possible38 - Our sample space reduces to $F$39 """)40 return41 42 43@app.cell(hide_code=True)44def _(mo):45 mo.md(r"""46 ## Definition of Conditional Probability47 48 The probability of event $E$ given that event $F$ has occurred is denoted as $P(E \mid F)$ and is defined as:49 50 $$P(E \mid F) = \frac{P(E \cap F)}{P(F)}$$51 52 This formula tells us that the conditional probability is the probability of both events occurring53 divided by the probability of the conditioning event.54 55 Let's start with a visual example.56 """)57 return58 59 60@app.cell61def _():62 import matplotlib.pyplot as plt63 from matplotlib_venn import venn364 import numpy as np65 return plt, venn366 67 68@app.cell(hide_code=True)69def _(mo, plt, venn3):70 # Create figure with square boundaries71 plt.figure(figsize=(10, 3))72 73 # Draw square sample space first74 rect = plt.Rectangle((-2, -2), 4, 4, fill=False, color="gray", linestyle="--")75 plt.gca().add_patch(rect)76 77 # Set the axis limits to show the full rectangle78 plt.xlim(-2.5, 2.5)79 plt.ylim(-2.5, 2.5)80 81 # Create Venn diagram showing E and F82 # For venn3, subsets order is: (100, 010, 110, 001, 101, 011, 111)83 # Representing: (A, B, AB, C, AC, BC, ABC)84 v = venn3(subsets=(30, 20, 10, 40, 0, 0, 0), set_labels=("E", "F", "Rest"))85 86 # Customize colors87 if v:88 for id in ["100", "010", "110", "001"]:89 if v.get_patch_by_id(id):90 if id == "100":91 v.get_patch_by_id(id).set_color("#ffcccc") # Light red for E92 elif id == "010":93 v.get_patch_by_id(id).set_color("#ccffcc") # Light green for F94 elif id == "110":95 v.get_patch_by_id(id).set_color(96 "#e6ffe6"97 ) # Lighter green for intersection98 elif id == "001":99 v.get_patch_by_id(id).set_color("white") # White for rest100 101 plt.title("Conditional Probability in Sample Space")102 103 # Remove ticks but keep the box visible104 plt.gca().set_yticks([])105 plt.gca().set_xticks([])106 plt.axis("on")107 108 # Add sample space annotation with arrow109 plt.annotate(110 "Sample Space (100)",111 xy=(-1.5, 1.5),112 xytext=(-2.2, 2),113 bbox=dict(boxstyle="round,pad=0.5", fc="white", ec="gray"),114 arrowprops=dict(arrowstyle="->"),115 )116 117 # Add explanation118 explanation = mo.md(r"""119 ### Visual Intuition120 121 In our sample space of 100 outcomes:122 123 - Event $E$ occurs in 40 cases (red region: 30 + 10)124 - Event $F$ occurs in 30 cases (green region: 20 + 10)125 - Both events occur together in 10 cases (overlap)126 - Remaining cases: 40 (to complete sample space of 100)127 128 When we condition on $F$:129 $$P(E \mid F) = \frac{P(E \cap F)}{P(F)} = \frac{10}{30} = \frac{1}{3} \approx 0.33$$130 131 This means: When we know $F$ has occurred (restricting ourselves to the green region),132 the probability of $E$ also occurring is $\frac{1}{3}$ - as 10 out of the 30 cases in the 133 green region also belong to the red region.134 """)135 136 mo.vstack([mo.center(plt.gcf()), explanation])137 return138 139 140@app.cell(hide_code=True)141def _(mo):142 mo.md(r"""143 Next, here's a function that computes $P(E \mid F)$, given $P( E \cap F)$ and $P(F)$144 """)145 return146 147 148@app.function149def conditional_probability(p_intersection, p_condition):150 if p_condition == 0:151 raise ValueError("Cannot condition on an impossible event")152 if p_intersection > p_condition:153 raise ValueError("P(E∩F) cannot be greater than P(F)")154 155 return p_intersection / p_condition156 157 158@app.cell159def _():160 # Example 1: Rolling a die161 # E: Rolling an even number (2,4,6)162 # F: Rolling a number greater than 3 (4,5,6)163 p_even_given_greater_than_3 = conditional_probability(2 / 6, 3 / 6)164 print("Example 1: Rolling a die")165 print(f"P(Even | >3) = {p_even_given_greater_than_3}") # Should be 2/3166 return167 168 169@app.cell170def _():171 # Example 2: Cards172 # E: Drawing a Heart173 # F: Drawing a Face card (J,Q,K)174 p_heart_given_face = conditional_probability(3 / 52, 12 / 52)175 print("\nExample 2: Drawing cards")176 print(f"P(Heart | Face card) = {p_heart_given_face}") # Should be 1/4177 return178 179 180@app.cell181def _():182 # Example 3: Student grades183 # E: Getting an A184 # F: Studying more than 3 hours185 p_a_given_study = conditional_probability(0.24, 0.40)186 print("\nExample 3: Student grades")187 print(f"P(A | Studied >3hrs) = {p_a_given_study}") # Should be 0.6188 return189 190 191@app.cell192def _():193 # Example 4: Weather194 # E: Raining195 # F: Cloudy196 p_rain_given_cloudy = conditional_probability(0.15, 0.30)197 print("\nExample 4: Weather")198 print(f"P(Rain | Cloudy) = {p_rain_given_cloudy}") # Should be 0.5199 return200 201 202@app.cell203def _():204 # Example 5: Error cases205 print("\nExample 5: Error cases")206 try:207 # Cannot condition on impossible event208 conditional_probability(0.5, 0)209 except ValueError as e:210 print(f"Error 1: {e}")211 212 try:213 # Intersection cannot be larger than condition214 conditional_probability(0.7, 0.5)215 except ValueError as e:216 print(f"Error 2: {e}")217 return218 219 220@app.cell(hide_code=True)221def _(mo):222 mo.md(r"""223 ## The Conditional Paradigm224 225 When we condition on an event, we enter a new probability universe. In this universe:226 227 1. All probability axioms still hold228 2. We must consistently condition on the same event229 3. Our sample space becomes the conditioning event230 231 Here's how our familiar probability rules look when conditioned on event $G$:232 233 | Rule | Original | Conditioned on $G$ |234 |------|----------|-------------------|235 | Axiom 1 | $0 \leq P(E) \leq 1$ | $0 \leq P(E \mid G) \leq 1$ |236 | Axiom 2 | $P(S) = 1$ | $P(S \mid G) = 1$ |237 | Axiom 3* | $P(E \cup F) = P(E) + P(F)$ | $P(E \cup F \mid G) = P(E \mid G) + P(F \mid G)$ |238 | Complement | $P(E^C) = 1 - P(E)$ | $P(E^C \mid G) = 1 - P(E \mid G)$ |239 240 *_For mutually exclusive events_241 """)242 return243 244 245@app.cell(hide_code=True)246def _(mo):247 mo.md(r"""248 ## Multiple Conditions249 250 We can condition on multiple events. The notation $P(E \mid F,G)$ means "_the probability of $E$251 occurring, given that both $F$ and $G$ have occurred._"252 253 The conditional probability formula still holds in the universe where $G$ has occurred:254 255 $$P(E \mid F,G) = \frac{P(E \cap F \mid G)}{P(F \mid G)}$$256 257 This is a powerful extension that allows us to update our probabilities as we receive258 multiple pieces of information.259 """)260 return261 262 263@app.function264def multiple_conditional_probability(265 p_intersection_all, p_intersection_conditions, p_condition266):267 """Calculate P(E|F,G) = P(E∩F|G)/P(F|G) = P(E∩F∩G)/P(F∩G)"""268 if p_condition == 0:269 raise ValueError("Cannot condition on an impossible event")270 if p_intersection_conditions == 0:271 raise ValueError(272 "Cannot condition on an impossible combination of events"273 )274 if p_intersection_all > p_intersection_conditions:275 raise ValueError("P(E∩F∩G) cannot be greater than P(F∩G)")276 277 return p_intersection_all / p_intersection_conditions278 279 280@app.cell281def _():282 # Example: College admissions283 # E: Getting admitted284 # F: High GPA285 # G: Good test scores286 287 # P(E∩F∩G) = P(Admitted ∩ HighGPA ∩ GoodScore) = 0.15288 # P(F∩G) = P(HighGPA ∩ GoodScore) = 0.25289 290 p_admit_given_both = multiple_conditional_probability(0.15, 0.25, 0.25)291 print("College Admissions Example:")292 print(293 f"P(Admitted | High GPA, Good Scores) = {p_admit_given_both}"294 ) # Should be 0.6295 296 # Error case: impossible condition297 try:298 multiple_conditional_probability(0.3, 0.2, 0.2)299 except ValueError as e:300 print(f"\nError case: {e}")301 return302 303 304@app.cell(hide_code=True)305def _(mo):306 mo.md(r"""307 ## 🤔 Test Your Understanding308 309 Which of these statements about conditional probability are true?310 311 <details>312 <summary>Knowing F occurred always decreases the probability of E</summary>313 ❌ False! Conditioning on F can either increase or decrease P(E), depending on how E and F are related.314 </details>315 316 <details>317 <summary>P(E|F) represents entering a new probability universe where F has occurred</summary>318 ✅ True! We restrict ourselves to only the outcomes where F occurred, making F our new sample space.319 </details>320 321 <details>322 <summary>If P(E|F) = P(E), then E and F must be the same event</summary>323 ❌ False! This actually means E and F are independent - knowing one doesn't affect the other.324 </details>325 326 <details>327 <summary>P(E|F) can be calculated by dividing P(E∩F) by P(F)</summary>328 ✅ True! This is the fundamental definition of conditional probability.329 </details>330 """)331 return332 333 334@app.cell(hide_code=True)335def _(mo):336 mo.md(r"""337 ## Summary338 339 You've learned:340 341 - How conditional probability updates our beliefs with new information342 - The formula $P(E \mid F) = P(E \cap F)/P(F)$ and its intuition343 - How probability rules work in conditional universes344 - How to handle multiple conditions345 346 In the next lesson, we'll explore **independence** - when knowing about one event347 tells us nothing about another.348 """)349 return350 351 352if __name__ == "__main__":353 app.run()354 