到L8(4×2^4))
做工艺优化和配方试验的朋友应该都体会过这种尴尬正交表附录翻了个遍L9(3^4)清一色三水平L8(2^7)清一色二水平L16(4^5)四水平够用但试验次数一下子跳到16次现场根本排不出来。等把因素和水平清单摆到桌面上——温度四个档、压力两个档、催化剂两种、转速只有快慢两档——你才意识到真正需要的是L8(4×2^4)这种“混着来”的多因素不同水平正交表。而这张表不是天上掉下来的它就是用并列法从L8(2^7)改出来的。我在做热压成型工艺优化时第一次用并列法当时手头只有一本附了常用标准正交表的参考书混合表刚好没有匹配的。硬着头皮把标准二水平表改造了一下试验方案顺利落地结果分析也没出问题。这篇文章就把我当时查资料、推原理、手工合并、再上机验证的全过程整理出来。适合正在做DOE但找不到合适混合表的人也适合想搞明白“标准表从哪来”的初学者。我会把并列法的原理、步骤、代码验证、常见坑一次讲透。1. 先搞懂正交表为什么“不够用”1.1 标准正交表的局限等水平是常态混合水平是刚需标准正交表分成两大类。一类是同水平的比如L4(2^3)、L8(2^7)、L16(2^15)、L9(3^4)、L27(3^13)、L16(4^5)、L25(5^6)。这类表的特点是每个因素的水平数都相同结构规整交互作用关系也配套齐全教科学里用得最多。另一类是混合水平的比如L8(4×2^4)、L16(4×2^12)、L16(4^2×2^9)、L18(2×3^7)、L36(2^11×3^12)。这类表允许不同因素取不同水平数更贴近实际。但问题在于标准混合表的覆盖范围太有限了。你自己列一张因素水平清单稍微复杂一点就找不到现成表。举个我实际遇到的情况一个工艺优化项目里温度需要4个水平压力只能取2个水平保温时间两种方案脱模剂也是两种型号。这种4222的组合L8(4×2^4)刚好能用不好还能换成别的。但如果你的因素是两个4水平再加三个2水平呢可以勉强用L16(4^2×2^9)。那三个4水平加两个3水平再加一个2水平呢标准表基本就没有了。这时候只有两条路要么放弃正交设计改做其他试验设计要么学会“改造”标准正交表。并列法就是后一条路里最成熟的技术。它的思路很简单既然标准表里都是等水平的列那我就在保持正交性的前提下把若干列合并成一列让这一列的水平数变多。这样一张同水平的标准表就能演化出各种混合水平表。1.2 正交性到底是什么从“均衡分散”说起要理解并列法为什么成立先得把正交性这个底层逻辑说清楚。以L8(2^7)为例8次试验7个二水平因素。拿其中任意两列出来看比如列1和列2它们组成的四种水平组合(1,1)、(1,2)、(2,1)、(2,2)在8次试验里恰好各出现2次。这就是正交性的直观含义任意两列之间水平组合完全均衡。这种“均衡分散”带来的好处就是主效应互不干扰。当我计算列1的水平1对应的试验结果平均值时列2水平1和水平2出现的次数是相等的所以列2的效应在平均值里被抵消掉了。换句话说每一列的主效应都可以独立估计不用担心中间混入其他列的影响。同时正交表还满足“整齐可比”任何一个水平下的数据量都是均匀的算极差、算方差都有意义。并列法动的脑筋就在这里如果我能把两列、三列甚至更多列合并成一列新的“超列”并且保留这种均衡性那这个新列就可以分配给一个水平数更多的因素。关键是怎么合并才不会破坏正交性。这就是下面要说的自由度守恒问题。1.3 自由度守恒并列法成立的核心依据试验设计里有个最重要的“总账”概念——自由度。一个二水平列能提供1个自由度三水平列提供2个自由度四水平列提供3个自由度。也就是水平数减1。对整张表来说8次试验的总自由度是7L8(2^7)恰好有7列每列1个自由度刚好分配完。现在的问题来了把两个二水平列合并成一个四水平列原来这两列一共提供2个自由度而合并后的四水平列需要3个自由度。还差1个自由度从哪里来答案就是这两个列的交互作用列。在L8(2^7)中列1和列2的交互作用占第3列这一列也是1个自由度。把列1、列2、列3三列一起合并自由度是1113正好等于一个四水平列的3个自由度。这就是并列法最核心的依据自由度守恒。合并前后表格的总自由度数不能变只能把若干列的“自由度”打包重组。推广一下就是从q水平的标准表出发要构造一个q^m水平的列需要占用的原列数为(q^m-1)/(q-1)。二水平表构造四水平列需要(4-1)/(2-1)3列构造八水平列需要7列三水平表构造九水平列需要(9-1)/(3-1)4列。这个公式做选表和规划时非常有用先把账算平后面才不会出错。2. 并列法的核心原理从2水平到4水平的“列合并”2.1 两列组合生成一列映射规则与示例并列法改造列的具体操作其实就是一个“映射”过程。拿L8(2^7)举例选第1列和第2列作为合并对象。这两列都是二水平的组合起来有四种可能(1,1)、(1,2)、(2,1)、(2,2)。把这四种组合按顺序映射成一个四水平列的四个取值第1列第2列新列4水平111122213224映射规则不是唯一的你完全可以把(1,2)对应成3、(2,1)对应成2只要是一一映射就行。因为新列的水平值本质上只是标签后续分析只看相对关系。但一般还是按字典序映射方便核对。逐行把L8(2^7)的第1列和第2列套进映射表得到的新列前8个值依次是1、1、2、2、3、3、4、4。每个四水平值正好出现2次。如果第1列和第2列本身是均衡的那这个结果必然成立不需要额外检查。2.2 为什么必须连带“交互作用列”一起并掉这是并列法最大的坎很多人第一次做就栽在这里。如果把第1列、第2列直接并成四水平列而放着第3列不管得到的表还能用吗答案是绝对不能用。原因要从交互作用说起。在正交表里如果两个因素之间真的存在交互效应而你没给它预留列它就会跑到别的列上去造成混杂。标准L8(2^7)的交互作用关系里列1×列2列3。也就是说列1和列2的乘积效应完整地反映在第3列里。当你把列1和列2合并成四水平列后这个四水平列其实已经包含了列3的信息四水平列的1个自由度差分成了原来的111其中就包括交互作用的那个自由度。如果此时第3列还独立存在那它就变成四水平列的一个“影子”两者高度相关。分析时你会发现第3列跟新四水平列的数据存在完全重复的结构正交性被破坏所有主效应估计都会乱套。所以合并时必须把两列以及它们的交互作用列一起并掉这就是“并列”这个词的真正含义——不是两列并列而是把一整个交互链并列打包。同样道理如果要从二水平表构造八水平列需要并7列这7列就是三个主效应列加它们的全部一阶、二阶交互列。列多了以后很难靠记忆找全必须查交互作用表。2.3 自由度对照表并前并后一个不多一个不少为了确认上面说的没问题我习惯在动手前先列一张自由度对照表。对L8(2^7)改造为L8(4×2^4)账目是这样的设计列构成自由度L8(2^7)7个二水平列7×17合并前3列列1、列2各1自由度列3交互1自由度3合并后1个四水平列3保留后4列4个二水平列4L8(4×2^4)1个四水平列 4个二水平列347总自由度没变还是7试验次数也还是8次但列的数量从7列变成了145列。这就是并列法能合理存在的数学基础。以后不管面对多复杂的改造方案先画一张这样的表自由度对上了再往下做。3. 手把手实操L8(2^7)并出L8(4×2^4)3.1 列合并的具体步骤我直接把当时的操作步骤写出来。第一步准备L8(2^7)标准表试验号列1列2列3列4列5列6列71111111121112222312211224122221152121212621221217221122182212112第二步确认列1和列2的交互列是第3列。这本教材上都写了L8的交互关系里1×23。第三步按前面那张映射表逐行生成新的四水平列。我把新列放在表的最左边删掉原来的列1、列2、列3保留列4到列7。得到下面这张改造后的表试验号A4水平B原列4C原列5D原列6空列原列7111111212222321122422211531212632121741221842112这时候你会发现新A列每个水平出现2次跟任何一个二水平列搭配时4×28种组合恰好各出现一次。比如A列和B列的组合(1,1)在第1种A1、B2在第2行(2,1)在第3行(2,2)在第4行后面依此类推。这就是正交性没有破坏的铁证。3.2 用Python验证并列后的正交性手工验证一两次还行列一多或者要并多组列我建议直接上脚本。下面这段代码我一直在用思路是把每个四水平列跟其他所有列做组合频次统计任意两列的组合频次如果全部相等就说明正交性成立。import numpy as np from collections import Counter L8 np.array([ [1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 2, 2, 2, 2], [1, 2, 2, 1, 1, 2, 2], [1, 2, 2, 2, 2, 1, 1], [2, 1, 2, 1, 2, 1, 2], [2, 1, 2, 2, 1, 2, 1], [2, 2, 1, 1, 2, 2, 1], [2, 2, 1, 2, 1, 1, 2], ]) def merge_two_cols_to_four(table, c1, c2): 把两个二水平列按(1,1)-1,(1,2)-2,(2,1)-3,(2,2)-4合并成四水平列 mapping {(1, 1): 1, (1, 2): 2, (2, 1): 3, (2, 2): 4} new_col [mapping[(row[c1], row[c2])] for row in table] return np.array(new_col) def check_balance(table, col_a, col_b): 检查两列之间的水平组合是否均衡出现 counts Counter((row[col_a], row[col_b]) for row in table) unique_counts set(counts.values()) return len(unique_counts) 1, dict(counts) # 合并列1和列2生成新四水平列原列3为交互列一并弃用 A merge_two_cols_to_four(L8, 0, 1) mixed_table np.column_stack([A, L8[:, 3], L8[:, 4], L8[:, 5], L8[:, 6]]) print(并列后的混合水平表) print(mixed_table) print(\n正交性验证新四水平列与其余每列的组合频次) for j in range(1, mixed_table.shape[1]): ok, cnt check_balance(mixed_table, 0, j) print(f与第{j}列的组合计数: {cnt}, 均衡: {ok})运行结果里每个四水平列与各二水平列的组合都是8种每种恰好1次check_balance返回True。这就用程序坐实了并列法改造结果的正交性。3.3 表头设计因素怎么放到各列上表改造完成接下来就是实战了。当时我做的热压成型工艺优化有四个因素热压温度A取4个水平150、160、170、180℃热压压力B取2个水平5、10MPa保温时间C取2个水平10、20分钟脱模剂类型D取2个水平I型、II型。表头分配很直观四水平因素A放在新生成的四水平列上三个二水平因素B、C、D依次放到原列4、列5、列6上原列7留空作为误差估计列。整个试验方案就8组按改造后的L8(4×2^4)执行。假设8次试验的响应值比如力学强度分别为78.5、82.3、87.1、84.6、79.8、85.2、88.4、86.7。做一个简单的极差分析因素水平1均值水平2均值水平3均值水平4均值极差A温度80.4085.8582.5087.557.15B压力83.4584.70--1.25C时间84.3883.78--0.60D脱模剂82.4085.75--3.35从极差看温度影响最大脱模剂次之压力和保温时间影响很小。需要提醒一句四水平因素的极差和二水平因素的极差不能直接比大小因为水平数越多极差被拉大的概率也越高。严谨的做法是用方差分析或者把极差除以对应自由度的平方根做折中修正。但这个案例里温度的极差优势太明显结论方向是可靠的。4. 更多并列方案L16系列与推广4.1 从L16(2^15)出发一组并列是L16(4×2^12)两组是L16(4^2×2^9)如果8次试验不够用就可以考虑L16(2^15)。这张表有15个二水平列总自由度15最多可以并出5个四水平列也就是L16(4^5)。实际使用时按需并列。只并一组列就是L16(4×2^12)可以容纳1个四水平因素加12个二水平因素。并两组就是L16(4^2×2^9)容纳2个四水平因素加9个二水平因素。依次类推得到L16(4^3×2^6)、L16(4^4×2^3)、L16(4^5)。关键问题是怎么选列组。不是随便拿三列就能并必须保证这三列是“两个主效应列加它们的交互列”而且不同的并列组之间不能有任何列重叠交互作用也不能互相牵扯。拿L16(2^15)来说第1列和第2列的交互在第3列所以(1,2,3)可以并成一组。第4列和第8列的交互在第12列所以(4,8,12)可以并成第二组。这两组互不相交可以共存于一张表中。更多的分组情况一定要对照你手上那张L16(2^15)的交互作用表来定不同教材列号编排若不一致照搬网上某些清单很容易翻车。4.2 3水平系列的推广L27(3^13)并出L27(9×3^9)并列法不是二水平表的专利三水平表同样可以改造只是逻辑稍微复杂一点。三水平表里两个三水平列合并成一个九水平列需要多少列参与先算自由度两个三水平列各有2自由度共4自由度九水平列需要8自由度还差4自由度。这4个自由度正是两个三水平列交互作用所占的列提供的。在三水平正交表中两个因素的交互作用要占2列每列2自由度合计4自由度。所以要把两列主效应列和2列交互列一起并掉总共4列才能得到一个九水平列。L27(3^13)有13个三水平列用掉4列得到九水平列后还剩9列所以得到L27(9×3^9)。如果你有某个因素真需要取9个水平比如配方的某个组分含量要设9个梯度就可以用这种方法。4.3 选表策略先用“试验次数总自由度1”推算规模我踩过好几次“表太大、试验做不完”的坑后来总结了一套选表流程分享给大家。第一步列因素清单把每个因素的水平数写清楚。第二步计算总自由度需求所有因素的(水平数-1)求和再加上你想要考察的交互作用的自由度。第三步试验次数必须大于等于“总自由度1”否则信息量不够。第四步在满足试验次数上限的候选表里先看标准表再看标准混合表最后才考虑并列法改造。第五步如果用并列法计算需要的原列数从二水平表出发并四水平列消耗3列并八水平列消耗7列从三水平表出发并九水平列消耗4列。这个数字直接决定你从哪张基表开始。举个实例有一个四水平因素、三个二水平因素总自由度31116试验次数至少7次。L8正好是8次能用。L8(2^7)并一组列变成L8(4×2^4)完美贴合。如果你的需求是三个四水平因素加两个二水平因素总自由度3×31×211试验次数至少12次这时L16系列就是起步选项L8肯定装不下。5. 并列法 vs 拟水平法别把两个方法搞混5.1 方向相反的两个操作很多初学者会把并列法和拟水平法弄混因为两个都是解决混合水平问题的招数但方向正好相反。并列法是从低水平列“升级”出高水平列把二水平列合并成四水平列本质是增加单列的容量代价是消耗更多列。拟水平法正好反过来当某个因素的实际水平数少于正交表列的水平数时把少的水平位补一个已有水平。比如某因素实际只有2个水平但我用的是L9(3^4)这张三水平表于是把这个因素的水平1再重复一次当作第3个“伪水平”。这样做的结果是该因素在试验中出现3次水平1、3次水平2、0次真正的水平3试验次数分配不再完全均衡。拟水平法没增加列的容量而是降低了列的使用效率所以自由度上是“虚”的分析时该因素实际有效的自由度仍然是1而不是三水平列表面的2。5.2 什么时候用并列法、什么时候用拟水平法判断依据主要看水平数之间有没有幂次关系。如果你的高水平因素水平数是低水平因素水平数的整数幂比如42^2、82^3、93^2优先用并列法。因为并列法可以保持每一列都被充分利用试验点均衡分散后续分析最干净。如果某个因素的实际水平数比正交表列的水平数少又找不到更合适的表那就用拟水平法。典型的场景是因素A三水平、因素B二水平、因素C三水平想用少量试验完成手头只有L9(3^4)这时B就只能用拟水平法塞进三水平列。需要提醒的是拟水平法的均衡性有一定损失B的水平1在9次试验中出现次数会比水平2多极差分析时要特别小心最好用方差分析做校正。而并列法改造后的表是严格均衡的试验次数分配不会出这种问题。6. 实操中的常见问题与排查技巧6.1 常见问题速查表我把这几年做混合水平设计时遇到的问题整理成了表方便大家快速对照。现象/问题原因解决办法并列后新列水平数不均匀合并时选错了列交互作用列没有被并掉核对交互作用表必须包含两列及交互列并完发现试验次数不够安排所有因素基表容量不够并列消耗列数超出预期先算自由度再选更大的基表因素水平是3和2混合并列法用不了并列法只支持幂次关系2→4/83→9等查标准混合表L18(2×3^7)、L36或换用拟水平法并列后的混合表查不到交互作用表混合表一般不配套完整交互表交互作用重要时改用更大的同水平表并预留交互列手工改造后正交性不确定缺少验证环节用脚本对任意两列做组合频次统计频次一致即正交不同书上同一张表的列号不一样正交表列号编排存在差异以你手上那个版本为基准对照交互表确认6.2 并列法的三大局限与应对第一个局限是水平数必须是幂次关系。二水平列只能并成四水平、八水平三水平列只能并成九水平、二十七水平。凡是想从二水平表并出三水平列的都属于“不可能任务”趁早放弃。遇到这种情况我的建议是直接去找标准混合表L18(2×3^7)、L36(2^11×3^12)或者考虑改用其他设计方法。第二个局限是交互作用信息会丢失。一旦并列被合并的列内部交互作用就被“吃掉”了之后再想单独分析这些交互效应没有干净的自由度可用。如果你对某个交互项很感兴趣那就不要把它所在的列并掉要在改造前就把交互列预留出来或者干脆选更大的表。第三个局限是混合表不“标准”审稿或者写报告时需要说明构造来源。我的做法是在试验方法部分明确写“采用并列法由L16(2^15)标准正交表构造L16(4×2^12)混合水平表”再附上映射规则和正交性验证结果。这样既专业又透明评审人不会质疑表来源不明。6.3 分享一个我常用的复核习惯最后讲一个我在实际项目中养成的习惯无论表是手工改造的还是软件生成的拿到手后的第一件事就是跑一遍组合频次统计。不是怀疑工具而是防止版本差异导致的错误。有一次我照着一本老教材的L16(2^15)交互表选列结果教材采用的列号顺序跟另一份资料不一致选出来的列组压根不对正交性验证直接报警好在及时发现否则整个试验方案都会出错。这个习惯也推荐给大家。验证代码不复杂就是把任意两列的水平组合做一个Counter统计看是否有全等频次。验证通过了再往下优化就行。试验设计这种事前面省一分钟后面可能花十天去填坑。我个人的体会是并列法最大的价值不是让你多记住一张混合表而是帮你真正理解为什么正交表能够“以小博大”。自己动手把列合并一次再做一遍正交性验证你对正交表的信任就完全不一样了。以后再遇到找不到标准表的项目也不会慌拿一支笔或者几行Python一张合适的设计表就能自己“造”出来。