You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何按指定概率权重从嵌套字典抽取符合分布的姓名

问题描述

假设我有如下嵌套姓名字典:

name_library = {
    'us': {
        'male': {'given_names': ['Alex', 'Bob', 'Charlie']},
        'female': {'given_names': ['Alice', 'Betty', 'Claire']}
    },
    'uk': {
        'male': {'given_names': ['aaa', 'Bbb', 'cc']},
        'female': {'given_names': ['ppp', 'ddd', 'sss']}
    }
}

需要实现按概率抽取姓名的逻辑,要求:

  • 抽取结果中60%为美国(us)地区姓名,40%为英国(uk)地区姓名
  • 抽取结果中男性、女性姓名占比各为50%

之前尝试参考加权概率选择字典键的思路实现,但当前场景逻辑更复杂;也曾考虑先提取字典内所有姓名再对全量姓名做分布分配,但该方案逻辑不合理,之前尝试的全量提取代码如下:

# all_possible_names = [
#     name
#     for list_of_names in [
#         self.library[area][gender][
#             "given_names"
#         ]
#         for gender in self.genders
#         for area in self.name_areas
#     ]
#     for name in list_of_names
# ]
# print(all_possible_names)

实现方案

不要把所有名字拉平到一个列表再分配权重,这种方案会被不同分类下的名字数量干扰,后续调整权重也非常麻烦。用分层加权抽样的思路即可,两个维度的权重独立计算,完全不受各分类下名字数量的影响:

  1. 先单独按地区权重抽取选中的地区
  2. 再单独按性别权重抽取选中的性别
  3. 最后从对应地区、性别的名字列表中随机抽取一个名字即可

代码实现

用Python标准库random就能实现,不需要额外依赖:

import random

# 姓名字典
name_library = {
    'us': {
        'male': {'given_names': ['Alex', 'Bob', 'Charlie']},
        'female': {'given_names': ['Alice', 'Betty', 'Claire']}
    },
    'uk': {
        'male': {'given_names': ['aaa', 'Bbb', 'cc']},
        'female': {'given_names': ['ppp', 'ddd', 'sss']}
    }
}

# 权重配置,后续调整比例直接改这里就行
CONFIG = {
    "areas": [("us", 0.6), ("uk", 0.4)],
    "genders": [("male", 0.5), ("female", 0.5)]
}

def get_random_name() -> str:
    # 按权重选地区
    selected_area = random.choices(
        population=[item[0] for item in CONFIG["areas"]],
        weights=[item[1] for item in CONFIG["areas"]],
        k=1
    )[0]
    # 按权重选性别
    selected_gender = random.choices(
        population=[item[0] for item in CONFIG["genders"]],
        weights=[item[1] for item in CONFIG["genders"]],
        k=1
    )[0]
    # 从对应名字池随机选一个
    return random.choice(name_library[selected_area][selected_gender]["given_names"])

# 测试:抽1000个验证占比
if __name__ == "__main__":
    res = [get_random_name() for _ in range(1000)]
    print(res[:10]) # 打印前10个结果示例

方案优势

  • 权重控制精准:不会因为某类名字数量多/少打乱地区、性别的占比要求
  • 维护成本低:后续新增地区、调整性别/地区权重、新增名字分类,只需要修改配置和对应字典即可,不需要改动核心抽样逻辑
  • 逻辑简单:没有复杂的权重换算,分层处理比全量名字算权重的思路好理解很多

如果需要批量抽取时严格保证占比完全精准(比如抽10个必须6个us、4个uk,5男5女),可以先按权重计算好每个分类需要抽取的固定数量,再从对应名字池无放回抽样即可,常规业务场景下上述概率抽样的方案已经完全够用。


内容的提问来源于stack exchange,提问作者Ahmad Anis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:18:22