Full Factorial Designs¶
Full factorial designs include every possible combination of factor levels, providing complete information about main effects and all interactions between factors.
When to Use Full Factorial Designs¶
- Small number of factors: Typically 2-4 factors with 2-3 levels each
- Complete understanding needed: When you need to understand all interactions
- Sufficient resources: When you can afford the number of experimental runs
- Baseline studies: When establishing a foundation for future experiments
Available Builders¶
FullFactorialDesignBuilder¶
The general-purpose builder for full factorial designs with factors having any number of levels.
import daspi as dsp
# Mixed level design: 2×3×2 = 12 runs
temperature = dsp.Factor('Temperature', (150, 200))
pressure = dsp.Factor('Pressure', (10, 12, 15)) # 3 levels
catalyst = dsp.Factor('Catalyst', ('A', 'B'), is_categorical=True)
builder = dsp.FullFactorialDesignBuilder(
temperature, pressure, catalyst,
replicates=2,
central_points=3,
blocks='highest',
shuffle=True
)
design = builder.build_design(corrected=False)
FullFactorial2kDesignBuilder¶
Specialized builder for 2-level factorial designs (2^k designs). These are the most common experimental designs.
import daspi as dsp
# 2^3 design: 2×2×2 = 8 runs
temperature = dsp.Factor('Temperature', (150, 200))
pressure = dsp.Factor('Pressure', (10, 15))
time = dsp.Factor('Time', (30, 60))
builder = dsp.FullFactorial2kDesignBuilder(
temperature, pressure, time,
replicates=2,
central_points=4,
shuffle=True
)
design = builder.build_design(corrected=False)
Design Features¶
Replication¶
Replication helps estimate experimental error and increases precision:
# Each factor combination run 3 times
builder = dsp.FullFactorialDesignBuilder(
factor_a, factor_b,
replicates=3
)
Central Points¶
Central points help detect curvature in the response and estimate pure error:
# Add 5 center point runs to each block
builder = dsp.FullFactorial2kDesignBuilder(
factor_a, factor_b,
central_points=5
)
Blocking¶
Blocking helps control for nuisance variables:
# Block by highest-order interaction (recommended)
builder = dsp.FullFactorialDesignBuilder(
factor_a, factor_b, factor_c,
blocks='highest'
)
# Block by specific interaction
builder = dsp.FullFactorialDesignBuilder(
factor_a, factor_b, factor_c,
blocks=['A', 'B'] # Block by A×B interaction
)
# Simple blocking (not confounded)
builder = dsp.FullFactorialDesignBuilder(
factor_a, factor_b, factor_c,
blocks=4 # Split into 4 blocks evenly
)
Design Size Considerations¶
| Factors | Levels | Runs | Suitable For |
|---|---|---|---|
| 2 | 2×2 | 4 | Quick screening |
| 3 | 2×2×2 | 8 | Small studies |
| 4 | 2×2×2×2 | 16 | Standard studies |
| 5 | 2×2×2×2×2 | 32 | Large studies |
| 3 | 3×3×3 | 27 | Response surfaces |
API Reference¶
daspi.doe.FullFactorialDesignBuilder(*factors, replicates=1, blocks=1, central_points=0, shuffle=True)
¶
Bases: BaseDesignBuilder
Builder for full factorial designs.
| PARAMETER | DESCRIPTION |
|---|---|
factors
|
Factors defining the design space.
TYPE:
|
replicates
|
Number of replicates. Must be positive, by default 1.
TYPE:
|
blocks
|
Number of blocks or block assignment strategy. For more
information, see the docstring of the
TYPE:
|
central_points
|
Number of central points to be added to each block. These are used to test linear effects. Must be non-negative. If set to 0, no central points are added. by default 0.
TYPE:
|
shuffle
|
Whether to shuffle the design, by default True.
TYPE:
|
Examples:
Create a full factorial design with two factors, each with two levels:
import daspi as dsp
factor_a = dsp.Factor('A', (1, 2))
factor_b = dsp.Factor('B', (10, 20))
builder = dsp.FullFactorialDesignBuilder(factor_a, factor_b)
df = builder.build_design(corrected=False)
print(df)
std_order run_order central_point replica block A B
0 0 0 1 1 1 1 10
1 1 1 1 1 1 1 20
2 2 2 1 1 1 2 10
3 3 3 1 1 1 2 20
Create a full factorial corrected design with two factors, each with two levels, and 3 replicates and split into blocks using the highest interaction:
import daspi as dsp
import numpy as np
np.random.seed(42) # optional for reproducibility
factor_a = dsp.Factor('A', (1, 2))
factor_b = dsp.Factor('B', (10, 20))
builder = dsp.FullFactorialDesignBuilder(
factor_a, factor_b, replicates=3, blocks='highest')
df = builder.build_design(corrected=True)
print(df)
std_order run_order central_point replica block A B
0 0 0 1 1 -1.0 -1.0
1 1 1 1 1 1.0 1.0
2 5 2 1 2 1.0 1.0
3 2 3 1 2 -1.0 -1.0
4 4 4 1 3 -1.0 -1.0
5 3 5 1 3 1.0 1.0
6 9 6 1 1 1.0 -1.0
7 6 7 1 1 -1.0 1.0
8 7 8 1 2 1.0 -1.0
9 8 9 1 2 -1.0 1.0
10 11 10 1 3 1.0 -1.0
11 10 11 1 3 -1.0 1.0
| RAISES | DESCRIPTION |
|---|---|
AssertionError
|
If any of the parameters are invalid: - At least one factor is required. - All factors must be instances of Factor class. - Number of replicates must be positive. - Number of blocks must be positive. |
daspi.doe.FullFactorial2kDesignBuilder(*factors, replicates=1, blocks=1, central_points=0, shuffle=True)
¶
Bases: FullFactorialDesignBuilder
Builder for full factorial designs with 2-level factors. This class is a specialization of FullFactorialDesignBuilder for the case where all factors have exactly 2 levels.
This design also supports replicates, central points, and blocks, and can be used to explore interactions between factors.
| PARAMETER | DESCRIPTION |
|---|---|
factors
|
Factors defining the design space. All factors must have exactly 2 levels.
TYPE:
|
replicates
|
Number of replicates. Must be positive, by default 1.
TYPE:
|
blocks
|
Block assignment: integer for evenly spaced blocks, str | List[str] for user-defined block generator, or Literal 'highest'/'replica'. Must be positive or 'highest'/'replica', by default 1.
TYPE:
|
central_points
|
Number of central points to be added to each block. These are used to test linear effects. Must be non-negative. If set to 0, no central points are added. by default 0.
TYPE:
|
shuffle
|
Whether to shuffle the design, by default True
TYPE:
|
Examples:
Create a full factorial design with two factors, each with two levels:
import daspi as dsp
factor_a = dsp.Factor('A', (0, 1))
factor_b = dsp.Factor('B', (0, 1))
builder = dsp.FullFactorial2kDesignBuilder(
factor_a, factor_b, shuffle=False)
df = builder.build_design(corrected=False)
print(df)
std_order run_order central_point replica block A B
0 0 0 1 1 1 0 0
1 1 1 1 1 1 0 1
2 2 2 1 1 1 1 0
3 3 3 1 1 1 1 1
Create a randomized full factorial corrected design with two factors, each with two levels, and 3 replicates, blocks by the highest interaction and 2 central points per block to test linear effects:
import daspi as dsp
import numpy as np
np.random.seed(42) # optional for reproducibility
factor_a = dsp.Factor('A', (0, 1))
factor_b = dsp.Factor('B', (0, 1))
builder = dsp.FullFactorial2kDesignBuilder(
factor_a, factor_b, replicates=3, central_points=2,
blocks='highest', shuffle=True)
df = builder.build_design(corrected=True)
print(df)
std_order run_order central_point replica block A B
0 1 0 1 1 1 1 1
1 5 1 1 2 1 1 1
2 0 2 1 1 1 -1 -1
3 7 3 0 1 1 0 0
4 2 4 1 2 1 -1 -1
5 4 5 1 3 1 -1 -1
6 3 6 1 3 1 1 1
7 6 7 0 2 1 0 0
8 11 8 1 1 2 1 -1
9 15 9 0 3 2 0 0
10 8 10 1 1 2 -1 1
11 12 11 1 2 2 -1 1
12 13 12 1 2 2 1 -1
13 10 13 1 3 2 -1 1
14 9 14 1 3 2 1 -1
15 14 15 0 4 2 0 0
| RAISES | DESCRIPTION |
|---|---|
AssertionError
|
If any of the parameters are invalid: - All factors must have exactly 2 levels. - Number of replicates must be positive. - Number of central points must be non-negative. - Number of blocks must be positive. |