用 Python 计算联合概率和条件概率

前言

概率论听起来像是数学课本里枯燥的公式,但实际上它无处不在------你早上出门前纠结"要不要带伞",本质上就是在做一次概率判断。

今天我们要聊的联合概率条件概率,是概率论中最基础也最实用的两个概念。

联合概率和条件概率到底是什么?

联合概率

联合概率 ,简单来说,就是两件事同时发生的概率

比如:今天既下雨、你又选择了打车上班的概率。这两件事需要同时满足,缺一不可。

数学上,事件 A 和事件 B 同时发生的概率记作 P(A ∩ B)P(A, B)

🌰 生活类比:联合概率就像在问------"一个随机选出来的日子里,既下雨又是周一"的概率有多大?两个条件都要满足。

条件概率

条件概率 则不太一样。它问的是:在已知某件事已经发生的前提下,另一件事发生的概率

比如:已知今天下雨了,在这种情况下你选择打车上班的概率是多少?这里"下雨"是已知条件,我们只关注下雨天里你打车的比例。

数学上,在事件 B 已经发生的条件下,事件 A 发生的概率记作 P(A | B),读作"在 B 条件下 A 的概率"。

🌰 生活类比:条件概率就像在问------"在所有周一的样本里,有多少比例同时在下雨?"你先把范围缩小到"周一",再看其中下雨的比例。

两者的核心区别

一句话总结:联合概率看的是"交集占总体"的比例,条件概率看的是"交集占条件"的比例

如果你有一个数据集,联合概率的分母是全部数据 ,而条件概率的分母是符合条件的那一部分数据。这个区别是理解后续代码的关键。

场景示例------天气与通勤方式

理论说完了,我们来构建一个具体的生活场景。

假设你记录了自己过去 200 个工作日的通勤数据,包括两个信息:

  • 天气状况:晴天(Sunny)、雨天(Rainy)、阴天(Cloudy)
  • 通勤方式:步行(Walk)、骑车(Bike)、打车(Taxi)

数据如下(200 天的统计结果):

天气 \ 通勤方式 步行 骑车 打车 合计
晴天 40 35 15 90
雨天 5 10 45 60
阴天 25 15 10 50
合计 70 60 70 200

这个表格能帮我们回答很多有趣的问题:

  • "某天既下雨又打车"的概率是多少?------联合概率
  • "已知下雨了,当天打车"的概率是多少?------条件概率
  • "已知打车了,当天是下雨天"的概率是多少?------另一个方向的条件概率

代码实现

准备数据

首先,我们需要把上面的表格转换成 Python 可以处理的形式。

最直接的方式是用 pandas 创建一个 DataFrame

python 复制代码
import pandas as pd
import numpy as np

# 创建原始数据:展开成 200 行
data = {
    'Weather': ['Sunny']*90 + ['Rainy']*60 + ['Cloudy']*50,
    'Commute': (
        ['Walk']*40 + ['Bike']*35 + ['Taxi']*15 +
        ['Walk']*5 + ['Bike']*10 + ['Taxi']*45 +
        ['Walk']*25 + ['Bike']*15 + ['Taxi']*10
    )
}

df = pd.DataFrame(data)
print(df.head())
print(f"\n总记录数: {len(df)}")

输出:

plain 复制代码
  Weather Commute
0   Sunny    Walk
1   Sunny    Walk
2   Sunny    Walk
3   Sunny    Walk
4   Sunny    Walk

总记录数: 200

计算联合概率

联合概率 = 同时满足两个条件的记录数 / 总记录数

比如,计算"雨天且打车"的联合概率:

python 复制代码
total = len(df)

# 计算联合概率:雨天 AND 打车
joint_count = len(df[(df['Weather'] == 'Rainy') & (df['Commute'] == 'Taxi')])
joint_prob = joint_count / total

print(f"P(雨天, 打车) = {joint_count} / {total} = {joint_prob:.3f}")
# 输出: P(雨天, 打车) = 45 / 200 = 0.225

你可以用同样的方式计算任意组合:

python 复制代码
# 晴天且步行
joint_sunny_walk = len(df[(df['Weather'] == 'Sunny') & (df['Commute'] == 'Walk')]) / total
print(f"P(晴天, 步行) = {joint_sunny_walk:.3f}")  # 0.200

# 阴天且骑车
joint_cloudy_bike = len(df[(df['Weather'] == 'Cloudy') & (df['Commute'] == 'Bike')]) / total
print(f"P(阴天, 骑车) = {joint_cloudy_bike:.3f}")  # 0.075

计算条件概率

条件概率 = 同时满足两个条件的记录数 / 满足条件的记录数

比如,计算"已知下雨的情况下,打车"的概率:

python 复制代码
# 先筛选出下雨天的所有记录
rainy_data = df[df['Weather'] == 'Rainy']
rainy_total = len(rainy_data)

# 在下雨天的记录中,统计打车的数量
taxi_in_rainy = len(rainy_data[rainy_data['Commute'] == 'Taxi'])

conditional_prob = taxi_in_rainy / rainy_total
print(f"P(打车 | 雨天) = {taxi_in_rainy} / {rainy_total} = {conditional_prob:.3f}")
# 输出: P(打车 | 雨天) = 45 / 60 = 0.750

注意这里的分母是 60(下雨天的总数),而不是总记录数 200。这就是联合概率和条件概率最本质的区别。

再看几个例子:

python 复制代码
# 已知晴天的情况下,步行的概率
sunny_data = df[df['Weather'] == 'Sunny']
prob_walk_given_sunny = len(sunny_data[sunny_data['Commute'] == 'Walk']) / len(sunny_data)
print(f"P(步行 | 晴天) = {prob_walk_given_sunny:.3f}")  # 40/90 = 0.444

# 已知打车的情况下,下雨的概率
taxi_data = df[df['Commute'] == 'Taxi']
prob_rainy_given_taxi = len(taxi_data[taxi_data['Weather'] == 'Rainy']) / len(taxi_data)
print(f"P(雨天 | 打车) = {prob_rainy_given_taxi:.3f}")  # 45/70 = 0.643

封装成通用函数

为了方便复用,可以把上面的逻辑封装成函数:

python 复制代码
def joint_probability(df, col1, val1, col2, val2):
    """
    计算两个事件同时发生的联合概率
    """
    total = len(df)
    count = len(df[(df[col1] == val1) & (df[col2] == val2)])
    return count / total

def conditional_probability(df, given_col, given_val, target_col, target_val):
    """
    计算在给定条件下,目标事件发生的概率
    P(target_val | given_val)
    """
    subset = df[df[given_col] == given_val]
    if len(subset) == 0:
        return 0.0
    count = len(subset[subset[target_col] == target_val])
    return count / len(subset)

# 使用示例
print(joint_probability(df, 'Weather', 'Rainy', 'Commute', 'Taxi'))        # 0.225
print(conditional_probability(df, 'Weather', 'Rainy', 'Commute', 'Taxi'))  # 0.750

用透视表一次看全

如果想一次性看到所有组合的联合概率和条件概率,可以用 pandas 的 crosstab 和归一化功能:

python 复制代码
# 联合概率表(所有组合的概率之和 = 1)
joint_table = pd.crosstab(df['Weather'], df['Commute'], normalize='all')
print("联合概率表:")
print(joint_table.round(3))

输出:

plain 复制代码
Commute  Bike   Taxi   Walk
Weather                    
Cloudy   0.075  0.050  0.125
Rainy    0.050  0.225  0.025
Sunny    0.175  0.075  0.200
python 复制代码
# 条件概率表(按行归一化:每行的和 = 1)
# 即 P(通勤方式 | 天气)
conditional_table = pd.crosstab(df['Weather'], df['Commute'], normalize='index')
print("\n条件概率表 P(通勤方式 | 天气):")
print(conditional_table.round(3))

输出:

plain 复制代码
Commute  Bike   Taxi   Walk
Weather                    
Cloudy   0.300  0.200  0.500
Rainy    0.167  0.750  0.083
Sunny    0.389  0.167  0.444

从条件概率表中可以直观地看到:下雨天打车概率高达 75%,而晴天步行概率也有 44%------这些数字背后藏着你的通勤习惯。

这两个概率能用在哪里?

理解这两个概念之后,你会发现它们几乎可以用在任何涉及"两个因素同时考虑"的场景中:

场景 联合概率问的是 条件概率问的是
电商推荐 用户是女性 购买了某商品 已知用户是女性,购买某商品的概率
健康管理 年龄大于 50 有高血压 已知年龄大于 50,有高血压的概率
金融风控 信用分低 逾期还款 已知信用分低,逾期还款的概率
市场营销 居住在一线城市 订阅了会员 已知居住在一线城市,订阅会员的概率
天气预报 早上阴天 下午下雨 已知早上阴天,下午下雨的概率

本质上,只要你有一个二维(或多维)的数据集,就可以用这两个工具来挖掘其中的规律。

总结

回顾一下文章的内容:

  1. 联合概率 P(A, B) = 两件事同时发生的概率,分母是全部数据
  2. 条件概率 P(A | B) = 在 B 已发生的前提下 A 发生的概率,分母是符合条件 B 的数据
  3. 两者通过公式 P(A, B) = P(A | B) × P(B) 相互联系
  4. Python 实现的核心就是筛选数据 + 计数 + 做除法,代码非常简洁

概率不是玄学,它就是用数据来量化不确定性

下次当你面临一个"两件事同时考虑"的决策时,不妨想想:我是在问联合概率,还是条件概率?答案本身,可能就是解决问题的关键一步。

相关推荐
葡萄成熟时 !1 小时前
泛型知识笔记
开发语言·笔记·python
fengyangaiGEO1 小时前
GEO 如何分析竞品的 AI 引用情况?
人工智能·python·信息可视化
2601_966949651 小时前
实时行情中的成交量 Volume 到底是什么?包含盘中撤单量吗?从交易数据语义到 QuantDash 实战解析
开发语言·人工智能·python·量化·quantdash·量化数据源
you鬰2 小时前
datawhale--llm-algo-leetcode9️⃣ SFT Training Loop
python·datawhale
叫我:松哥2 小时前
基于flask仿小米商城管理系统,使用flask开的一个商场网站
数据库·后端·python·flask
智购科技无人售货机工厂2 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
2401_868534782 小时前
校园网规划与设计
python·pygame
小猴子爱上树2 小时前
跨境电商AI批量图片翻译工具,视频字幕翻译免费试用
人工智能·python·音视频
zx_741484812 小时前
【Python入门】爬虫实战:Requests + XPath 从基础到实战
开发语言·爬虫·python