ThSQCA 入門 第3回: 解の種類と、複数の解

ThSQCA
tutorial
複雑解、倹約解、中間解を小さな例で説明します。1つの閾値に最小解が複数あるときの扱いも見ます。
Author

Yuki Toyoda

Published

October 5, 2026

第2回では、4つのスイープをすべて実行しました。丁寧な分析には、まだ2つの問いが残っています。1つ目は、QCAには3種類の解(複雑解、倹約解、中間解)がありますが、どれを使うべきか、です。2つ目は、1つのセルに最小解が複数あるときは、どうするか、です。この回では、2つ目の、もっと小さな練習用データで、両方に答えます。

2つ目の練習用データ

企業向けソフトウェアのアカウントを、60件シミュレーションで作ります。各アカウントは、更新スコア(RNW)と、3つの評価をもちます。信頼(TRU)、価格(PRC)、サポート(SUP)で、どれも0〜10点です。この模擬の世界では、信頼が高く、かつ、価格かサポートのどちらかが高いときに、更新が高くなります。3つの評価は強く相関しているので、条件の組み合わせのうち、観察されないものが出てきます。これは意図的です。観察されない組み合わせこそ、3種類の解が、違う扱いをするものだからです。

library(ThSQCA)
library(QCA)
Loading required package: admisc

To cite package QCA in publications, please use:
  Dusa, Adrian (2019) QCA with R. A Comprehensive Resource.
  Springer International Publishing.
練習用データ2
make_demo_data2 <- function(n = 60, seed = 89, rho = 0.85) {
  set.seed(seed)
  clip <- function(x) pmin(10, pmax(0, round(x)))
  L   <- rnorm(n)
  mk  <- function() clip(6 + 2 * (rho * L + sqrt(1 - rho^2) * rnorm(n)))
  TRU <- mk(); PRC <- mk(); SUP <- mk()
  RNW <- clip(pmin(TRU, pmax(PRC, SUP)) + rnorm(n, 0, 0.7))
  data.frame(RNW, TRU, PRC, SUP)
}

demo2 <- make_demo_data2()
head(demo2)
  RNW TRU PRC SUP
1   3   3   4   4
2   6   8   7   7
3   9   9   9   7
4   5   5   4   6
5  10  10   8   9
6   1   2   4   5

観察されない組み合わせ(「論理残余」)

条件が3つあり、それぞれが高いか低いかなら、可能な組み合わせは 2 x 2 x 2 = 8通りです。QCAは、それらを真理表に並べます。QCAパッケージで、真理表を手で作ってみましょう。アウトカムは更新が5以上、各条件の「高い」は7以上とします。

bin2 <- data.frame(
  RNW = as.integer(demo2$RNW >= 5),
  TRU = as.integer(demo2$TRU >= 7),
  PRC = as.integer(demo2$PRC >= 7),
  SUP = as.integer(demo2$SUP >= 7)
)

tt2 <- truthTable(bin2, outcome = "RNW", conditions = c("TRU", "PRC", "SUP"),
                  incl.cut = 0.8, n.cut = 1, show.cases = FALSE)
tt2

  OUT: output value
    n: number of cases in configuration
 incl: sufficiency inclusion score
  PRI: proportional reduction in inconsistency

    TRU PRC SUP   OUT    n   incl  PRI  
1    0   0   0     0     30  0.433 0.433
2    0   0   1     1     7   0.857 0.857
4    0   1   1     1     3   1.000 1.000
6    1   0   1     1     3   1.000 1.000
7    1   1   0     1     4   1.000 1.000
8    1   1   1     1     13  1.000 1.000

左側の行番号を見てください。可能な8通りのうち、現れるのは6通りだけです(3行目と5行目がありません)。たとえば、信頼だけが高いアカウントや、価格の評価だけが高いアカウントが、データにないからです。欠けている組み合わせが、論理残余です。列 n は、各組み合わせのアカウント数、incl は、それらがどれだけ一貫して更新しているか、OUT は、組み合わせが十分と認められるだけの一貫性があるとき1になります。

件数を棒グラフにすると、欠けている組み合わせがすぐ分かります。1本の棒が、可能な8通りのうちの1つで、真理表の行と同じ順に並べています。図の中の語は英語のままです。

cells <- expand.grid(SUP = 0:1, PRC = 0:1, TRU = 0:1)[, c("TRU", "PRC", "SUP")]
cells$n <- mapply(function(a, b, c) sum(bin2$TRU == a & bin2$PRC == b & bin2$SUP == c),
                  cells$TRU, cells$PRC, cells$SUP)
cells$label <- paste0(ifelse(cells$TRU == 1, "TRU", "~TRU"), "*",
                      ifelse(cells$PRC == 1, "PRC", "~PRC"), "*",
                      ifelse(cells$SUP == 1, "SUP", "~SUP"))

op <- par(mar = c(4.5, 9, 3, 1))
n_rev <- rev(cells$n)
bp <- barplot(n_rev, horiz = TRUE, names.arg = rev(cells$label), las = 1,
              col = "#233A9A", xlim = c(0, max(cells$n) * 1.35),
              xlab = "Number of accounts",
              main = "Accounts per combination")
for (i in seq_along(n_rev)) {
  if (n_rev[i] == 0) {
    text(0, bp[i], "not observed (remainder)", pos = 4, col = "#B45309", cex = 0.9, font = 2)
  } else {
    text(n_rev[i], bp[i], n_rev[i], pos = 4, cex = 0.9)
  }
}

8通りの組み合わせの横棒グラフ。3つとも高くない組み合わせは30アカウント、サポートだけが高いものは7、価格とサポートが高く信頼が高くないものは3、信頼とサポートが高く価格が高くないものは3、信頼と価格が高くサポートが高くないものは4、3つとも高いものは13。価格だけが高い組み合わせと、信頼だけが高い組み合わせは0件で、not observedと表示されている。

信頼、価格、サポートの高低の、可能な8通りの組み合わせごとのアカウント数。2つの組み合わせは観察されていません。
par(op)

アカウントが0件の2つの組み合わせが、残余です。Boolean最小化には、それらを確かめる事例がないので、解の種類ごとに、残余の扱いを決めることになります。

残余が重要なのは、Boolean最小化が、式を短くするために、残余を使えるからです。3種類の解は、残余を使うかどうか、どう使うかが違います。

解の種類 使う残余 include dir.exp
複雑解 なし ""(既定) NULL
倹約解 式を短くする、すべての残余 "?" NULL
中間解 自分が述べた期待と合う残余だけ "?" たとえば c(1, 1, 1)

ここで dir.exp = c(1, 1, 1) は、「信頼が高いこと、価格の評価が高いこと、サポートが高いことは、どれも更新に有利だと期待する」という意味です。

3種類の解を並べる

同じアウトカム閾値スイープ(更新が5、6、7、8)を、解の種類だけ変えて、3回実行します。

thr2  <- c(TRU = 7, PRC = 7, SUP = 7)
cond2 <- c("TRU", "PRC", "SUP")

run2 <- function(...) {
  otSweep(dat = demo2, outcome = "RNW", conditions = cond2, sweep_range = 5:8,
          thrX = thr2, incl.cut = 0.8, n.cut = 1, ...)
}

res_cx <- run2()                                     # complex
res_ps <- run2(include = "?")                        # parsimonious
Warning: Multiple equivalent solutions exist for thrY = 5 (n_solutions > 1).
Only the first solution (M1) and its fit metrics are shown. Use
generate_report() for full analysis.
res_im <- run2(include = "?", dir.exp = c(1, 1, 1))  # intermediate

data.frame(
  thrY         = 5:8,
  complex      = res_cx$summary$expression,
  parsimonious = res_ps$summary$expression,
  intermediate = res_im$summary$expression
)
  thrY            complex   parsimonious       intermediate
1    5      SUP + TRU*PRC      TRU + SUP      SUP + TRU*PRC
2    6 TRU*PRC + ~PRC*SUP TRU + ~PRC*SUP TRU*PRC + ~PRC*SUP
3    7            TRU*SUP        TRU*SUP            TRU*SUP
4    8        No solution    No solution        No solution

出力と一緒に表示される警告は、ThSQCAからの注意です。更新が5のとき、倹約解の分析には、同じ長さの解が複数あります。これは、後で扱います。

更新が7のときは、3つとも一致して(TRU*SUP)、8ではどれも解がありません。5と6では、倹約解のほうが短くなります。たとえば、更新が5のとき、倹約解は TRU + SUP ですが、複雑解は SUP + TRU*PRC です。TRU だけの項は、「信頼は高いが、価格とサポートの評価が低い」という組み合わせをカバーしますが、この組み合わせは、データに現れません。倹約解は、この観察されない組み合わせも十分だろう、と仮定する立場です。複雑解は、そのような仮定を置きません。このデータでは、たまたま、中間解は複雑解と一致します。

選び方です。

解 向いている場面 強み 注意
複雑解 探索。観察されない事例に仮定を置きたくないとき すべての主張が、観察された事例に基づく 式が長くなることがある
倹約解 最大限の単純化を見たいとき 式がいちばん短い もっともらしくない残余に頼ることがある
中間解 理論に基づいて報告するとき もっともらしい残余だけを使う 根拠のある dir.exp が要る

どれを選んでも、スイープ全体で同じものを使い、どれを使ったかを書いてください。

1つのセルに、最小解が複数あるとき

Boolean最小化は、同じ真理表から、同じ長さの解を複数返すことがあります。既定では、ThSQCAは最初の1つ(M1)を報告し、解の数を n_solutions に記録します。すべてを見るには、extract_mode = "all" を使います。

res_all <- run2(include = "?", extract_mode = "all")
Warning: Multiple equivalent solutions exist for thrY = 5 (n_solutions > 1).
Only the first solution (M1) and its fit metrics are shown. Use
generate_report() for full analysis.
summary(res_all)
OTS Summary
=========== 

Analysis Parameters:
  Outcome: RNW 
  Conditions: TRU, PRC, SUP 
  Consistency cutoff: 0.8 
  Frequency cutoff: 1 

Results by Threshold:

 thrY                   expression inclS  covS n_solutions
    5 M1: TRU + SUP; M2: PRC + SUP 0.967 0.690           2
    6           M1: TRU + ~PRC*SUP 0.963 0.788           1
    7                  M1: TRU*SUP 0.875 0.667           1
    8                  No solution    NA    NA           0

Note: 1 threshold setting(s) had multiple solutions.
      Use generate_report() for full details.

更新が5のとき、倹約解の分析は、等しく最小な2つの解、TRU + SUP と PRC + SUP を見つけます。それぞれが、別の観察されない組み合わせに頼っているので、データだけでは、どちらかを優先できません。ThSQCAは、このようなとき、注意を表示します。

コンパクトに見たいときは、extract_mode = "essential" を使います。すべての解に含まれる項と、それ以外を分けます。

res_ess <- run2(include = "?", extract_mode = "essential")
Warning: Multiple equivalent solutions exist for thrY = 5 (n_solutions > 1).
Only the first solution (M1) and its fit metrics are shown. Use
generate_report() for full analysis.
res_ess$summary[, c("thrY", "expression", "selective_terms",
                    "unique_terms", "n_solutions")]
  thrY     expression selective_terms   unique_terms n_solutions
1    5            SUP       TRU + PRC M1:TRU; M2:PRC           2
2    6 TRU + ~PRC*SUP            <NA>           <NA>           1
3    7        TRU*SUP            <NA>           <NA>           1
4    8    No solution            <NA>           <NA>           0
項の種類 意味 ここでは(更新が5)
本質項(essential) すべての解に含まれる SUP
選択項(selective) 一部の解に含まれる TRU と PRC
固有項(unique) 1つの解にだけ含まれる M1では TRU、M2では PRC

ThSQCAは、代替案を記録します。しかし、どれを優先するかは、理論的な判断で、研究者に残されます。

次回

最終回の第4回では、結果を報告できる形にします。Markdown形式のレポート、構成図、QCAパッケージとの照合です。

使ったソフトウェア: R 4.6.1、QCA 3.25.5、ThSQCA 2.0.9