如何按指定顺序计算字典笛卡尔积 匹配doepy全因子设计输出顺序
问题描述
基于全因子实验设计生成所有参数组合的DataFrame时,doepy库的build.full_fact()方法在组合规模较大时运行速度很慢,改用笛卡尔积方法计算虽然速度更快,但输出的组合顺序和doepy结果不一致,需要让笛卡尔积输出顺序完全匹配doepy的结果。
原有测试代码如下:
import pandas as pd from doepy import build from tqdm.contrib.itertools import product gas_dict = { 'Velocity (m/s)': [0.00000000E+00, 0.10000000E+00, 0.20000000E+00, 0.30000000E+00, 0.40000000E+00, 0.60000000E+00, 0.10000000E+01], 'Pressure (Pa)': [0.10000000E+06, 0.50000000E+06, 0.10000000E+07, 0.20000000E+07, 0.40000000E+07], 'Temperature': [0.30000000E+03, 0.40000000E+03, 0.50000000E+03, 0.60000000E+03,], 'Equivalence Ratio': [0.10000000E+00, 0.50000000E+00, 0.60000000E+00, 0.70000000E+00, 0.80000000E+00, 0.90000000E+00, 0.10000000E+01, 0.11000000E+01, 0.12000000E+01, 0.13000000E+01] } def product_dict(**kwargs): keys = kwargs.keys() vals = kwargs.values() for instance in product(*vals): yield dict(zip(keys, instance)) gas = build.full_fact(gas_dict) # 顺序正确的参考结果 gas_product = list(product_dict(**gas_dict)) # 顺序不匹配 gas_product = pd.DataFrame(gas_product)
顺序差异原因
tqdm.contrib.itertools.product和标准库itertools.product的迭代逻辑一致:传入的序列中,最右侧的序列迭代速度最快,最左侧的序列迭代速度最慢。
而doepy的build.full_fact()迭代逻辑相反:传入的参数字典中,最左侧的参数迭代速度最快,最右侧的参数迭代速度最慢,二者的迭代步进顺序完全相反,因此直接按原字典顺序传入计算笛卡尔积会得到顺序不一致的结果。
解决方法
计算笛卡尔积时将参数序列逆序传入,生成单条组合记录时再将键值对逆序还原为原始参数顺序,最终输出的DataFrame即可和doepy结果完全一致,同时保留笛卡尔积计算的高性能与tqdm进度条功能。
修正后的实现代码:
def product_dict_match_doepy(**kwargs): keys = list(kwargs.keys()) # 逆序传入参数序列,对齐doepy的迭代步进逻辑 reversed_vals = [kwargs[key] for key in reversed(keys)] for instance in product(*reversed_vals): # 逆序拼接键值对,还原原始参数列顺序 yield dict(zip(reversed(keys), instance)) # 生成结果并验证 gas_doepy = build.full_fact(gas_dict) gas_product_fixed = pd.DataFrame(list(product_dict_match_doepy(**gas_dict))) # 一致性校验,返回True代表顺序和值完全匹配 print(gas_doepy.equals(gas_product_fixed))
效果说明
- 生成的全因子组合顺序、数值和doepy输出完全一致
- 计算性能和原生笛卡尔积相当,大规模参数组合场景下速度远高于doepy原生实现
- 保留tqdm进度条,大规模计算时可实时查看进度
内容的提问来源于stack exchange,提问作者Zizi96
相关产品推荐
相关产品推荐

