using StatsOrdinalPatterns, Random, Statistics, Printf, DataFrames, DistributionsReplication: Weiß and Kim (2025)
This page reproduces Table 8 of Weiß and Kim (2025). The table reports simulated rejection rates at level \(\alpha = 0.05\) for DGP 4, an SQMA(1,1) model with \((\beta_1, \beta_2, \beta_3) = (0.8, 0.8, 0.8)\), for the classical spatial ordinal pattern (SOP) classification and for the three refined ones.
Libraries
Statistics of the paper and their types in the package
The four column groups of Table 8 are the refinement argument of test_sop:
| Table 8 group | refinement |
|---|---|
| Ordinary types | OrdinaryType() |
| Rotation types | RotationType() |
| Direction types | DirectionType() |
| Diagonal types | DiagonalType() |
The columns within a group are its chart_choice:
| Table 8 column | chart_choice |
Rejects \(H_0\) when | Label below |
|---|---|---|---|
| \(\tilde{\tau}\) | TauTilde() |
\(\lvert\tilde{\tau}\rvert > c\) | tau_tilde |
| \(\widehat{H}\) | Shannon(base=exp(1)) |
rescaled \(\widehat{H} > c\) | H |
| \(\widehat{H}_{ex}\) | ShannonExtropy(base=exp(1)) |
rescaled \(\widehat{H}_{ex} > c\) | H_ex |
| \(\widehat{\Delta}\) | DistanceToWhiteNoise() |
\(\widehat{\Delta} > c\) | Delta |
\(\tilde{\tau}\) appears in the ordinary group only; the refined classifications have asymptotic theory for the entropy type charts. The rescaling of the entropy statistics and the generalized \(\chi^2\) critical value are what test_sop applies internally, and crit_val_sop returns the critical value for a given scheme, level and field size.
Setup
DGP 4 is the SQMA11 type of the package: dgp_params are the \(\beta_j\), eps_params are the exponents \((a, b, c)\) of the three error terms, written “\(1^a\,2^b\,3^c\)” in the paper, and M_rows, N_cols are the dimensions of the field. m and n in the table are the dimensions of the SOP matrix, so the field is \((m+1) \times (n+1)\).
Parameters of Table 8 and one field of DGP 4
β = (0.8, 0.8, 0.8) # dependence parameters of Table 8
level = 0.05 # nominal significance level
sizes = ((10, 10), (15, 15), (20, 20), (40, 25)) # SOP matrix dimensions (m, n)
reps = 10_000 # Monte Carlo replications
models = [
("DGP4-1", "1² 2² 3²", (2, 2, 2)),
("DGP4-2", "1² 2¹ 3²", (2, 1, 2)),
("DGP4-3", "1¹ 2¹ 3²", (1, 1, 2)),
("DGP4-4", "1² 2¹ 3¹", (2, 1, 1)),
]
entropies = [("H", Shannon(base=exp(1))), ("H_ex", ShannonExtropy(base=exp(1))), ("Delta", DistanceToWhiteNoise())]
schemes = [
("ord", OrdinaryType(), vcat([("tau_tilde", TauTilde())], entropies)),
("rot", RotationType(), entropies),
("dir", DirectionType(), entropies),
("diag", DiagonalType(), entropies),
]
stats = ["$(sn)_$(cn)" for (sn, _, cs) in schemes for (cn, _) in cs] # 13 columns
# One field of the DGP. `fill_mat_dgp_sop!` is the routine the ARL functions of the
# package use internally; it writes into the caller's buffers and returns a view of the
# field. `mat` receives the field, `mat_ma` the errors, `mat_ao` the additive outliers,
# which DGP 4 does not have.
sqma11(eps, m, n) = SQMA11(β, eps, m + 1, n + 1, Normal(0, 1), nothing)
buffers(dgp) = ntuple(_ -> zeros(dgp.M_rows + 1, dgp.N_cols + 1), 3)
draw_field!(dgp, mat, mat_ao, mat_ma) =
StatsOrdinalPatterns.fill_mat_dgp_sop!(dgp, dgp.dist, dgp.dist_ao, mat, mat_ao, mat_ma)A single test
One field of DGP 4 and one SOP test
Random.seed!(1)
dgp = sqma11((2, 2, 2), 10, 10)
Y = collect(draw_field!(dgp, buffers(dgp)...)) # copy out of the buffer
test_sop(Y, 1, 1; chart_choice=ShannonExtropy(base=exp(1)), refinement=DiagonalType(), alpha=level)SOPTestResult Chart: ShannonExtropy(base = 2.718281828459045) Statistic: 0.0169 ───────────────────────────── Asymptotic test Critical value: 0.015 p-value: 0.0309 Reject H₀: true
Running the power study
crit_val_sop returns the critical value alone, which depends on the field size, the level and the classification scheme, not on the data, so it is computed once per row of the table. test_sop additionally computes the \(p\) value, which for the entropy charts means evaluating a generalized \(\chi^2\) distribution numerically and which a power study does not use. Each replication then costs one stat_sop pass per classification scheme, and the charts of that scheme are read off the resulting \(\hat{\mathbf{p}}\) with chart_stat_sop.
Rejection rates of the 13 tests for one field size
# two sided for τ̃, upper tail on the rescaled statistic for the entropy charts
rejects(::TauTilde, p̂, crit) = abs(chart_stat_sop(p̂, TauTilde())) > crit
rejects(cc, p̂, crit) =
StatsOrdinalPatterns.rescale_sop(chart_stat_sop(p̂, cc), length(p̂), cc) > crit
function power(m, n, eps, reps; level=0.05)
dgp = sqma11(eps, m, n)
M, N = dgp.M_rows, dgp.N_cols
crits = [crit_val_sop(M, N, 1, 1; chart_choice=cc, refinement=ref, alpha=level)
for (_, ref, cs) in schemes for (_, cc) in cs]
tasks = map(Iterators.partition(1:reps, cld(reps, Threads.nthreads()))) do idx
Threads.@spawn begin
bufs = buffers(dgp) # one set of buffers per task
hits = zeros(Int, length(crits))
for _ in idx
Y = draw_field!(dgp, bufs...)
k = 0
for (_, ref, cs) in schemes
p̂ = stat_sop(Y, 1, 1; chart_choice=Shannon(base=exp(1)), refinement=ref)[2]
for (_, cc) in cs
k += 1
hits[k] += rejects(cc, p̂, crits[k])
end
end
end
hits
end
end
return sum(fetch.(tasks)) ./ reps
endThe shortcut has to give the same decision as test_sop in all 13 columns, not merely a similar one:
Check against test_sop
let dgp = sqma11((1, 1, 2), 20, 20), M = 21, N = 21
Y = collect(draw_field!(dgp, buffers(dgp)...))
ok = true
for (_, ref, cs) in schemes
p̂ = stat_sop(Y, 1, 1; chart_choice=Shannon(base=exp(1)), refinement=ref)[2]
for (_, cc) in cs
r = test_sop(Y, 1, 1; chart_choice=cc, refinement=ref, alpha=level)
c = crit_val_sop(M, N, 1, 1; chart_choice=cc, refinement=ref, alpha=level)
ok &= c ≈ r.asymp_crit && rejects(cc, p̂, c) == r.asymp_reject
end
end
(shortcut_matches_test_sop=ok,)
end(shortcut_matches_test_sop = true,)
With reps = 10_000 the page runs in a few seconds and the standard error of a rejection rate is at most \(\sqrt{0.25 / 10^4} = 0.005\).
Table 8: DGP 4, \((\beta_1, \beta_2, \beta_3) = (0.8, 0.8, 0.8)\)
Run the study for every model and field size
res = Dict(
(name, m, n) => power(m, n, eps, reps; level=level)
for (name, _, eps) in models for (m, n) in sizes
)Ordinary types
| Row | model | label | m | n | tau_tilde | H | H_ex | Delta |
|---|---|---|---|---|---|---|---|---|
| String | String | Int64 | Int64 | Float64 | Float64 | Float64 | Float64 | |
| 1 | DGP4-1 | 1² 2² 3² | 10 | 10 | 0.25 | 0.196 | 0.185 | 0.194 |
| 2 | DGP4-1 | 1² 2² 3² | 15 | 15 | 0.469 | 0.424 | 0.41 | 0.409 |
| 3 | DGP4-1 | 1² 2² 3² | 20 | 20 | 0.766 | 0.687 | 0.672 | 0.675 |
| 4 | DGP4-1 | 1² 2² 3² | 40 | 25 | 0.991 | 0.98 | 0.978 | 0.978 |
| 5 | DGP4-2 | 1² 2¹ 3² | 10 | 10 | 0.591 | 0.491 | 0.469 | 0.485 |
| 6 | DGP4-2 | 1² 2¹ 3² | 15 | 15 | 0.926 | 0.889 | 0.876 | 0.876 |
| 7 | DGP4-2 | 1² 2¹ 3² | 20 | 20 | 0.997 | 0.994 | 0.993 | 0.993 |
| 8 | DGP4-2 | 1² 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 | 1.0 |
| 9 | DGP4-3 | 1¹ 2¹ 3² | 10 | 10 | 0.382 | 0.312 | 0.301 | 0.31 |
| 10 | DGP4-3 | 1¹ 2¹ 3² | 15 | 15 | 0.702 | 0.666 | 0.651 | 0.65 |
| 11 | DGP4-3 | 1¹ 2¹ 3² | 20 | 20 | 0.943 | 0.913 | 0.907 | 0.908 |
| 12 | DGP4-3 | 1¹ 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 | 1.0 |
| 13 | DGP4-4 | 1² 2¹ 3¹ | 10 | 10 | 0.215 | 0.17 | 0.162 | 0.167 |
| 14 | DGP4-4 | 1² 2¹ 3¹ | 15 | 15 | 0.419 | 0.382 | 0.37 | 0.368 |
| 15 | DGP4-4 | 1² 2¹ 3¹ | 20 | 20 | 0.694 | 0.62 | 0.607 | 0.609 |
| 16 | DGP4-4 | 1² 2¹ 3¹ | 40 | 25 | 0.974 | 0.957 | 0.955 | 0.955 |
Rotation types
| Row | model | label | m | n | H | H_ex | Delta |
|---|---|---|---|---|---|---|---|
| String | String | Int64 | Int64 | Float64 | Float64 | Float64 | |
| 1 | DGP4-1 | 1² 2² 3² | 10 | 10 | 0.192 | 0.173 | 0.172 |
| 2 | DGP4-1 | 1² 2² 3² | 15 | 15 | 0.379 | 0.356 | 0.358 |
| 3 | DGP4-1 | 1² 2² 3² | 20 | 20 | 0.633 | 0.614 | 0.616 |
| 4 | DGP4-1 | 1² 2² 3² | 40 | 25 | 0.967 | 0.965 | 0.965 |
| 5 | DGP4-2 | 1² 2¹ 3² | 10 | 10 | 0.453 | 0.414 | 0.418 |
| 6 | DGP4-2 | 1² 2¹ 3² | 15 | 15 | 0.845 | 0.823 | 0.826 |
| 7 | DGP4-2 | 1² 2¹ 3² | 20 | 20 | 0.987 | 0.984 | 0.985 |
| 8 | DGP4-2 | 1² 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 |
| 9 | DGP4-3 | 1¹ 2¹ 3² | 10 | 10 | 0.293 | 0.275 | 0.276 |
| 10 | DGP4-3 | 1¹ 2¹ 3² | 15 | 15 | 0.608 | 0.587 | 0.589 |
| 11 | DGP4-3 | 1¹ 2¹ 3² | 20 | 20 | 0.877 | 0.868 | 0.869 |
| 12 | DGP4-3 | 1¹ 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 |
| 13 | DGP4-4 | 1² 2¹ 3¹ | 10 | 10 | 0.174 | 0.156 | 0.155 |
| 14 | DGP4-4 | 1² 2¹ 3¹ | 15 | 15 | 0.35 | 0.332 | 0.335 |
| 15 | DGP4-4 | 1² 2¹ 3¹ | 20 | 20 | 0.567 | 0.552 | 0.554 |
| 16 | DGP4-4 | 1² 2¹ 3¹ | 40 | 25 | 0.938 | 0.934 | 0.935 |
Direction types
| Row | model | label | m | n | H | H_ex | Delta |
|---|---|---|---|---|---|---|---|
| String | String | Int64 | Int64 | Float64 | Float64 | Float64 | |
| 1 | DGP4-1 | 1² 2² 3² | 10 | 10 | 0.124 | 0.129 | 0.124 |
| 2 | DGP4-1 | 1² 2² 3² | 15 | 15 | 0.274 | 0.271 | 0.269 |
| 3 | DGP4-1 | 1² 2² 3² | 20 | 20 | 0.504 | 0.5 | 0.498 |
| 4 | DGP4-1 | 1² 2² 3² | 40 | 25 | 0.934 | 0.931 | 0.931 |
| 5 | DGP4-2 | 1² 2¹ 3² | 10 | 10 | 0.854 | 0.868 | 0.862 |
| 6 | DGP4-2 | 1² 2¹ 3² | 15 | 15 | 0.998 | 0.998 | 0.998 |
| 7 | DGP4-2 | 1² 2¹ 3² | 20 | 20 | 1.0 | 1.0 | 1.0 |
| 8 | DGP4-2 | 1² 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 |
| 9 | DGP4-3 | 1¹ 2¹ 3² | 10 | 10 | 0.204 | 0.208 | 0.201 |
| 10 | DGP4-3 | 1¹ 2¹ 3² | 15 | 15 | 0.481 | 0.474 | 0.471 |
| 11 | DGP4-3 | 1¹ 2¹ 3² | 20 | 20 | 0.796 | 0.788 | 0.788 |
| 12 | DGP4-3 | 1¹ 2¹ 3² | 40 | 25 | 0.998 | 0.998 | 0.998 |
| 13 | DGP4-4 | 1² 2¹ 3¹ | 10 | 10 | 0.124 | 0.13 | 0.124 |
| 14 | DGP4-4 | 1² 2¹ 3¹ | 15 | 15 | 0.269 | 0.269 | 0.265 |
| 15 | DGP4-4 | 1² 2¹ 3¹ | 20 | 20 | 0.481 | 0.478 | 0.477 |
| 16 | DGP4-4 | 1² 2¹ 3¹ | 40 | 25 | 0.912 | 0.91 | 0.91 |
Diagonal types
| Row | model | label | m | n | H | H_ex | Delta |
|---|---|---|---|---|---|---|---|
| String | String | Int64 | Int64 | Float64 | Float64 | Float64 | |
| 1 | DGP4-1 | 1² 2² 3² | 10 | 10 | 0.265 | 0.269 | 0.261 |
| 2 | DGP4-1 | 1² 2² 3² | 15 | 15 | 0.543 | 0.551 | 0.548 |
| 3 | DGP4-1 | 1² 2² 3² | 20 | 20 | 0.819 | 0.825 | 0.823 |
| 4 | DGP4-1 | 1² 2² 3² | 40 | 25 | 0.998 | 0.998 | 0.998 |
| 5 | DGP4-2 | 1² 2¹ 3² | 10 | 10 | 0.462 | 0.444 | 0.438 |
| 6 | DGP4-2 | 1² 2¹ 3² | 15 | 15 | 0.853 | 0.843 | 0.845 |
| 7 | DGP4-2 | 1² 2¹ 3² | 20 | 20 | 0.989 | 0.988 | 0.988 |
| 8 | DGP4-2 | 1² 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 |
| 9 | DGP4-3 | 1¹ 2¹ 3² | 10 | 10 | 0.334 | 0.33 | 0.325 |
| 10 | DGP4-3 | 1¹ 2¹ 3² | 15 | 15 | 0.676 | 0.674 | 0.675 |
| 11 | DGP4-3 | 1¹ 2¹ 3² | 20 | 20 | 0.92 | 0.921 | 0.921 |
| 12 | DGP4-3 | 1¹ 2¹ 3² | 40 | 25 | 1.0 | 1.0 | 1.0 |
| 13 | DGP4-4 | 1² 2¹ 3¹ | 10 | 10 | 0.228 | 0.23 | 0.223 |
| 14 | DGP4-4 | 1² 2¹ 3¹ | 15 | 15 | 0.468 | 0.476 | 0.474 |
| 15 | DGP4-4 | 1² 2¹ 3¹ | 20 | 20 | 0.737 | 0.745 | 0.744 |
| 16 | DGP4-4 | 1² 2¹ 3¹ | 40 | 25 | 0.99 | 0.991 | 0.99 |
The paper prints the largest power value of each row in bold:
| Row | model | m | n | max_stat | rate |
|---|---|---|---|---|---|
| String | Int64 | Int64 | String | Float64 | |
| 1 | DGP4-1 | 10 | 10 | diag_H_ex | 0.269 |
| 2 | DGP4-1 | 15 | 15 | diag_H_ex | 0.551 |
| 3 | DGP4-1 | 20 | 20 | diag_H_ex | 0.825 |
| 4 | DGP4-1 | 40 | 25 | diag_H, diag_H_ex, diag_Delta | 0.998 |
| 5 | DGP4-2 | 10 | 10 | dir_H_ex | 0.868 |
| 6 | DGP4-2 | 15 | 15 | dir_H, dir_H_ex, dir_Delta | 0.998 |
| 7 | DGP4-2 | 20 | 20 | dir_H, dir_H_ex, dir_Delta | 1.0 |
| 8 | DGP4-2 | 40 | 25 | 13 columns tied | 1.0 |
| 9 | DGP4-3 | 10 | 10 | ord_tau_tilde | 0.382 |
| 10 | DGP4-3 | 15 | 15 | ord_tau_tilde | 0.702 |
| 11 | DGP4-3 | 20 | 20 | ord_tau_tilde | 0.943 |
| 12 | DGP4-3 | 40 | 25 | 10 columns tied | 1.0 |
| 13 | DGP4-4 | 10 | 10 | diag_H_ex | 0.23 |
| 14 | DGP4-4 | 15 | 15 | diag_H_ex | 0.476 |
| 15 | DGP4-4 | 20 | 20 | diag_H_ex | 0.745 |
| 16 | DGP4-4 | 40 | 25 | diag_H_ex | 0.991 |
Comparison with the published rates
entries compared: 208
largest absolute deviation: 0.012
mean absolute deviation: 0.003
Monte Carlo standard error: at most 0.005
The five largest deviations:
| Row | model | m | n | statistic | paper | replicated | dev |
|---|---|---|---|---|---|---|---|
| String | Int64 | Int64 | String | Float64 | Float64 | Float64 | |
| 1 | DGP4-4 | 20 | 20 | dir_H | 0.469 | 0.481 | 0.012 |
| 2 | DGP4-3 | 10 | 10 | ord_H_ex | 0.29 | 0.301 | 0.011 |
| 3 | DGP4-4 | 15 | 15 | dir_H | 0.258 | 0.269 | 0.011 |
| 4 | DGP4-2 | 15 | 15 | ord_tau_tilde | 0.916 | 0.926 | 0.01 |
| 5 | DGP4-3 | 10 | 10 | ord_Delta | 0.301 | 0.31 | 0.01 |