ここでの他の回答は、シーケンス内のさまざまな文字の全体的な出現に焦点を合わせています。これは、予期される「ランダムさ」の1つの側面である可能性があります。ただし、興味深いもう1つの側面は、シーケンス内の文字の順序の見かけ上のランダム性です。少なくとも、「ランダム性」は文字のベクトルの交換可能性を伴うと思います。これは「実行テスト」を使用してテストできます。実行テストは、シーケンス内の「実行」の数をカウントし、同じ文字を持つベクトルについて、交換可能性の帰無仮説の下で実行の総数をそのnull分布と比較します。「実行」を構成するものの正確な定義は、特定のテストによって異なります(たとえば、ここで同様の回答を参照してください))ですが、この場合、名目上のカテゴリーでは、自然な定義は、1つの文字のみで構成される連続したシーケンスを1つの「ラン」としてカウントすることです。
たとえば、あなたのシーケンスBABD-CABC-DACD-BACD
は一見ランダムではないように見えます(文字自体は表示されません。これは、この長いシーケンスではおそらく珍しいことです)。† これを正式にテストするために、互換性の実行テストを実行できます。このシーケンスでは、n=16 文字(各文字4つ)と r=16それぞれが1つの文字の1つのインスタンスで構成されます。観測された実行数は、交換可能性の仮説のもとで、そのヌル分布と比較できます。これはシミュレーションを介して行うことができます。これにより、シミュレーションのnull分布とテストのp値が得られます。この一連の文字の結果を下のグラフに示します。
このシーケンスの場合、(交換可能性の帰無仮説の下で)実行テストのp値は p=0.0537。これは、10%の有意水準では有意ですが、5%の有意水準では有意ではありません。交換不可能なシリーズ(つまり、ランダムでない順序)を示唆する証拠はいくつかありますが、証拠は特に強力ではありません。観測された文字列が長いほど、実行テストは、交換可能な文字列と交換不可能な文字列を区別するためのより大きな力を持ちます。(ご覧のように、この文字列はランダムではないという最初の一応の判断は間違っている可能性があります。p値は実際には予想していたほど低くはありません。)
最後に、このテストは文字列内の文字の順序のランダム性のみを調べることに注意することが重要です。これは、各タイプの文字の数を固定入力として受け取ります。このテストは、文字列内の文字の非交換性という意味で非ランダム性を検出しますが、異なる文字の全体的な確率という意味で「ランダム性」をテストしません。後者も「ランダム性」の指定された意味の一部である場合、この実行テストは、文字の全体的な数を調べ、これを仮説のnull分布と比較する別のテストで補強できます。
Rコード:上記のプロットとp値は、次のR
コードを使用して生成されました。
#Define the character string vector (as factors)
x <- factor(c(2,1,2,4, 3,1,2,3, 4,1,3,4, 2,1,3,4),
labels = c('A', 'B', 'C', 'D'))
#Define a function to calculate the runs for an input vector
RUNS <- function(x) { n <- length(x);
R <- 1;
for (i in 2:n) { R <- R + (x[i] != x[i-1]) }
R; }
#Simulate the runs statistic for k permutations
k <- 10^5;
set.seed(12345);
RR <- rep(0, k);
for (i in 1:k) { x_perm <- sample(x, length(x), replace = FALSE);
RR[i] <- RUNS(x_perm); }
#Generate the frequency table for the simulated runs
FREQS <- as.data.frame(table(RR));
#Calculate the p-value of the runs test
R <- RUNS(x);
R_FREQ <- FREQS$Freq[match(R, FREQS$RR)];
p <- sum(FREQS$Freq*(FREQS$Freq <= R_FREQ))/k;
#Plot estimated distribution of runs with test
library(ggplot2);
ggplot(data = FREQS, aes(x = RR, y = Freq/k, fill = (Freq <= R_FREQ))) +
geom_bar(stat = 'identity') +
geom_vline(xintercept = match(R, FREQS$RR)) +
scale_fill_manual(values = c('Grey', 'Red')) +
theme(legend.position = 'none',
plot.title = element_text(hjust = 0.5, face = 'bold'),
plot.subtitle = element_text(hjust = 0.5),
axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0))) +
labs(title = 'Runs Test - Plot of Distribution of Runs under Exchangeability',
subtitle = paste0('(Observed runs is black line, p-value = ', p, ')'),
x = 'Runs', y = 'Estimated Probability');
†読みやすくするために、シーケンスをダッシュで区切っています。ダッシュは分析にとって重要ではありません。