adas.utils
packageDesign of Experiments, the tidy way
University of Trento
rtug::25.1, 2025-05-30
adas.utils
packageDoE aims at getting the most information from a minimum of experiments
Create a non-replicated full factorial plan with three factors, two levels each (\(2^3\)):
A B C Y StdOrder RunOrder
1 -1 -1 -1 NA 1 5
2 1 -1 -1 NA 2 1
3 -1 1 -1 NA 3 7
4 1 1 -1 NA 4 3
5 -1 -1 1 NA 5 2
6 1 -1 1 NA 6 6
7 -1 1 1 NA 7 8
8 1 1 1 NA 8 4
Then save it (typ. as CSV), perform the experiments, fill the Y
yield column, and load it back for the analysis
For a fractional factorial plan, we reject one half of the FP according to a defining relationship: \(I=ABC\), which can be transformed as \(C=AB\)
We remove rows where the sign of \(C\) is the product of \(A\) and \(B\):
A B C Y StdOrder RunOrder
2 1 -1 -1 NA 2 4
3 -1 1 -1 NA 3 3
5 -1 -1 1 NA 5 1
8 1 1 1 NA 8 2
But mind you! for this to work, columns A
, B
, and C
must NOT be factors! (in the R sense)
Remark on defining relationships
It holds the signs algebra: \(X\cdot X=I,~I\cdot X = X\), thus \(CI = ABCC~\rightarrow~C=AB\)
Analyzing the FP is mostly a matter of:
Y~A*B*C
lm()
to fit the modelresiduals()
to check the residuals for normality and patternsanova()
to analyze the modelBut if the FP is non-replicated, you can’t fit a model unless you remove some terms from the general linear model Y~A*B*C
. To do so, Daniel’s method suggests to make a Q-Q plot of the effects: not straightforward
As an example for a \(2^4\) FP, the Daniel’s Q-Q plot of the effects can be obtained by:
Problems:
F
?)adas.utils
packageThe package is available on CRAN:
Don’t forget to look at the vignette:
Base \(2\cdot 2^2\) FP:
Factorial Plan Design Matrix
Defining Relationship: ~ A * B
Factors: A B
Levels: -1 1
Fraction: NA
Type: plain
# A tibble: 8 × 7
StdOrder RunOrder .treat .rep A B Y
<int> <int> <chr> <int> <dbl> <dbl> <lgl>
1 1 8 (1) 1 -1 -1 NA
2 2 2 a 1 1 -1 NA
3 3 6 b 1 -1 1 NA
4 4 5 ab 1 1 1 NA
5 5 4 (1) 2 -1 -1 NA
6 6 1 a 2 1 -1 NA
7 7 7 b 2 -1 1 NA
8 8 3 ab 2 1 1 NA
Note
Note the Yates’ treatment names in .treat
column
We can tie factors with corresponding parameter names:
Factorial Plan Design Matrix
Defining Relationship: ~ A * B
Factors: A B
Levels: -1 1
Fraction: NA
Type: plain
Factor names:
A: Temperature
B: Pressure
# A tibble: 8 × 7
StdOrder RunOrder .treat .rep A B Y
<int> <int> <chr> <int> <dbl> <dbl> <lgl>
1 1 1 (1) 1 -1 -1 NA
2 2 5 a 1 1 -1 NA
3 3 7 b 1 -1 1 NA
4 4 4 ab 1 1 1 NA
5 5 6 (1) 2 -1 -1 NA
6 6 8 a 2 1 -1 NA
7 7 2 b 2 -1 1 NA
8 8 3 ab 2 1 1 NA
Actual scales can be added for reference:
Factorial Plan Design Matrix
Defining Relationship: ~ A * B
Factors: A B
Levels: -1 1
Fraction: NA
Type: plain
Scales suffix: .scaled
Scaled factors:
A.scaled: [20, 25]
B.scaled: [75, 125]
Factor names:
A: Temperature
B: Pressure
# A tibble: 8 × 7
.treat .rep A B A.scaled B.scaled Y
<chr> <int> <dbl> <dbl> <dbl> <dbl> <lgl>
1 (1) 1 -1 -1 20 75 NA
2 a 1 1 -1 25 75 NA
3 b 1 -1 1 20 125 NA
4 ab 1 1 1 25 125 NA
5 (1) 2 -1 -1 20 75 NA
6 a 2 1 -1 25 75 NA
7 b 2 -1 1 20 125 NA
8 ab 2 1 1 25 125 NA
We can augment a \(2^n\) FP with a central treatment:
Factorial Plan Design Matrix
Defining Relationship: ~ A * B * C
Factors: A B C
Levels: -1 1
Fraction: NA
Type: centered
Scales suffix: _s
Scaled factors:
B_s: [10, 20]
# A tibble: 6 × 9
StdOrder RunOrder .treat .rep A B C B_s Y
<int> <int> <chr> <int> <dbl> <dbl> <dbl> <dbl> <lgl>
1 7 2 bc 1 -1 1 1 20 NA
2 8 7 abc 1 1 1 1 20 NA
3 9 12 center 1 0 0 0 15 NA
4 10 10 center 2 0 0 0 15 NA
5 11 11 center 3 0 0 0 15 NA
6 12 9 center 4 0 0 0 15 NA
And then further augment the FP with axial treatments to get a rotatable Composite Centered Design (CCD):
# A tibble: 9 × 8
StdOrder .treat .rep A B A_s B_s Y
<int> <chr> <int> <dbl> <dbl> <dbl> <dbl> <lgl>
1 1 (1) 1 -1 -1 7 10 NA
2 2 a 1 1 -1 18 10 NA
3 3 b 1 -1 1 7 20 NA
4 4 ab 1 1 1 18 20 NA
5 5 center 1 0 0 12.5 15 NA
6 6 axial 1 0 -1.41 12.5 7.93 NA
7 7 axial 1 -1.41 0 4.72 15 NA
8 8 axial 1 1.41 0 20.3 15 NA
9 9 axial 1 0 1.41 12.5 22.1 NA
Note
Automatically scaling CCDs helps a lot in correctly defining process settings for each treatment
And then further augment the FP with axial treatments to get a rotatable Centered Composite Design (CCD):
Note
Of course it works on higher dimensions as well
We can fraction a \(2^n\) FP by adding subsequent defining relationships:
Factorial Plan Design Matrix
Defining Relationship: ~ A * B * C * D * E
Factors: A B C D E
Levels: -1 1
Fraction: I=ABCD I=BCDE
Type: fractional
# A tibble: 8 × 9
.treat A B C D E Y ABCD BCDE
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl> <dbl> <dbl>
1 (1) -1 -1 -1 -1 -1 NA 1 1
2 bc -1 1 1 -1 -1 NA 1 1
3 bd -1 1 -1 1 -1 NA 1 1
4 cd -1 -1 1 1 -1 NA 1 1
5 abe 1 1 -1 -1 1 NA 1 1
6 ace 1 -1 1 -1 1 NA 1 1
7 ade 1 -1 -1 1 1 NA 1 1
8 abcde 1 1 1 1 1 NA 1 1
You can save the design matrix as CSV file (for collecting experimental data), then load it back into the original FP object (thus preserving attributes):
Factorial Plan Design Matrix
Defining Relationship: ~ A * B * C * D
Factors: A B C D
Levels: -1 1
Fraction: I=ABCD
Type: fractional
# A tibble: 8 × 9
StdOrder .treat .rep A B C D Y ABCD
<int> <chr> <int> <dbl> <dbl> <dbl> <dbl> <lgl> <dbl>
1 1 (1) 1 -1 -1 -1 -1 NA 1
2 4 ab 1 1 1 -1 -1 NA 1
3 6 ac 1 1 -1 1 -1 NA 1
4 7 bc 1 -1 1 1 -1 NA 1
5 10 ad 1 1 -1 -1 1 NA 1
6 11 bd 1 -1 1 -1 1 NA 1
7 13 cd 1 -1 -1 1 1 NA 1
8 16 abcd 1 1 1 1 1 NA 1
Note
The saved CSV file has a commented header with FFP details (e.g. defining relationships, factors names, scales, etc.)
Fractioning a FP creates alias structures: the adas.utils
package can help you with that too:
Defining relationships:
I=ABC I=BCD I=AD
A B AB C AC BC ABC D AD BD ABD CD ACD BCD ABCD
A 0 0 0 0 0 1 0 3 0 0 0 0 0 0 2
B 0 0 0 0 1 0 0 0 0 0 3 2 0 0 0
AB 0 0 0 1 0 0 0 0 0 3 0 0 2 0 0
C 0 0 1 0 0 0 0 0 0 2 0 0 3 0 0
AC 0 1 0 0 0 0 0 0 0 0 2 3 0 0 0
BC 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3
ABC 0 0 0 0 0 0 0 0 2 0 0 0 0 3 0
D 3 0 0 0 0 2 0 0 0 0 0 0 0 0 1
AD 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0
BD 0 0 3 2 0 0 0 0 0 0 0 0 1 0 0
ABD 0 3 0 0 2 0 0 0 0 0 0 1 0 0 0
CD 0 2 0 0 3 0 0 0 0 0 1 0 0 0 0
ACD 0 0 2 3 0 0 0 0 0 1 0 0 0 0 0
BCD 0 0 0 0 0 0 3 0 1 0 0 0 0 0 0
ABCD 2 0 0 0 0 3 0 1 0 0 0 0 0 0 0
The alias matrix can be plotted directly, via ggplot2
:
Note
The third generator is the dependent one, i.e. the one that has all terms not in common in the first two generators
The adas.utils
package can also help you with Daniel’s method: the daniel_plot_hn()
function takes a linear model object and returns a half-normal plot of the effects:
It’s easy to build a Pareto chart of the effects in a linear model:
Tukey’s test TukeyHSD()
is not compatible with ggplot2
, and its output pretty limited (and not very appealing). The adas.utils
package provides a ggTukey()
function that can be used to plot the results of Tukey’s test, also with multiple groups:
Only pre-tidyverse packages as:
DoE.base
FrF2
adas.utils
is currently v1.2.0
on CRAN
install.packages("adas.utils")
v1.2.1
devtools::install_github("pbosetti/adas.utils")
Presentations made in Quarto can be interactive too…
Presentations made in Quarto can be interactive too…