This note aims to introduce QCA package in R by Dusa (2019).
References:
# install.packages("tidyverse")
# install.packages("QCA")
# install.packages("venn")
library(tidyverse)
library(QCA)
library(venn)
The Lipset dataset used in Rihoux and Ragin (2009=2016)
Call help description.
?LR
Rihoux & Ragin (2009=2016, Ch.3)
LR %>%
select(-STB) %>%
mutate(
DEV = if_else(DEV >= 600, 1, 0),
URB = if_else(URB >= 50, 1, 0),
LIT = if_else(LIT >= 75, 1, 0),
IND = if_else(IND >= 30, 1, 0),
SURV = if_else(SURV >= 0, 1, 0)
) -> LCinit
Truth table with contradictions
(incl.cut = c(1, 0.01)
)
LCinit %>%
truthTable("SURV", incl.cut = c(1, 0.01),
show.cases = TRUE, complete = TRUE) -> ttLCinit
ttLCinit
##
## OUT: output value
## n: number of cases in configuration
## incl: sufficiency inclusion score
## PRI: proportional reduction in inconsistency
##
## DEV URB LIT IND OUT n incl PRI cases
## 1 0 0 0 0 0 5 0.000 0.000 GR,IT,PT,RO,ES
## 2 0 0 0 1 ? 0 - -
## 3 0 0 1 0 C 4 0.250 0.250 EE,FI,HU,PL
## 4 0 0 1 1 ? 0 - -
## 5 0 1 0 0 ? 0 - -
## 6 0 1 0 1 ? 0 - -
## 7 0 1 1 0 ? 0 - -
## 8 0 1 1 1 1 1 1.000 1.000 CZ
## 9 1 0 0 0 ? 0 - -
## 10 1 0 0 1 ? 0 - -
## 11 1 0 1 0 1 1 1.000 1.000 IE
## 12 1 0 1 1 C 3 0.667 0.667 AU,FR,SE
## 13 1 1 0 0 ? 0 - -
## 14 1 1 0 1 ? 0 - -
## 15 1 1 1 0 ? 0 - -
## 16 1 1 1 1 C 4 0.750 0.750 BE,DE,NL,UK
Minimization for explaining both 1 and C.
ttLCinit %>%
minimize(explain = "1, C", detail = TRUE) -> csLCinit
csLCinit
##
## M1: ~URB*LIT*~IND + URB*LIT*IND + (DEV*~URB*LIT) <-> SURV
## M2: ~URB*LIT*~IND + URB*LIT*IND + (DEV*LIT*IND) <-> SURV
##
## -------------------
## inclS PRI covS covU (M1) (M2) cases
## ---------------------------------------------------------------------------------
## 1 ~URB*LIT*~IND 0.400 0.400 0.250 0.125 0.125 0.250 EE,FI,HU,PL; IE
## 2 URB*LIT*IND 0.800 0.800 0.500 0.125 0.500 0.125 CZ; BE,DE,NL,UK
## ---------------------------------------------------------------------------------
## 3 DEV*~URB*LIT 0.750 0.750 0.375 0.000 0.250 IE; AU,FR,SE
## 4 DEV*LIT*IND 0.714 0.714 0.625 0.000 0.250 AU,FR,SE; BE,DE,NL,UK
## ---------------------------------------------------------------------------------
## M1 0.615 0.615 1.000
## M2 0.615 0.615 1.000
Prime implicant chart
csLCinit$PIchart
##
## 3 8 11 12 16
## DEV*~URB*LIT - - x x -
## DEV*LIT*IND - - - x x
## ~URB*LIT*~IND x - x - -
## URB*LIT*IND - x - - x
Venn diagram of the solution
csLCinit %>% venn()
Minimization for explaining 1 and C, including ?, so called parsimonious solution.
ttLCinit %>%
minimize(explain = "1, C", include = "?", detail = TRUE) -> psLCinit
psLCinit
##
## M1: LIT <-> SURV
##
## inclS PRI covS covU cases
## ------------------------------------------------------------------------------
## 1 LIT 0.615 0.615 1.000 - EE,FI,HU,PL; CZ; IE; AU,FR,SE; BE,DE,NL,UK
## ------------------------------------------------------------------------------
## M1 0.615 0.615 1.000
Simplifying assumptions
psLCinit$SA
## $M1
## DEV URB LIT IND
## 4 0 0 1 1
## 7 0 1 1 0
## 15 1 1 1 0
psLCinit$PIchart
##
## 3 8 11 12 16
## DEV - - x x x
## URB - x - - x
## LIT x x x x x
## IND - x - x x
psLCinit$solution[[1]] %>% venn(snames = "DEV, URB, LIT, IND")
LC %>%
truthTable("SURV", show.cases = TRUE) %>%
minimize(details = TRUE) -> csLC
csLC
##
## M1: DEV*~URB*LIT*STB + DEV*LIT*IND*STB <-> SURV
##
## inclS PRI covS covU cases
## -------------------------------------------------------------------
## 1 DEV*~URB*LIT*STB 1.000 1.000 0.500 0.250 FI,IE; FR,SE
## 2 DEV*LIT*IND*STB 1.000 1.000 0.750 0.500 FR,SE; BE,CZ,NL,UK
## -------------------------------------------------------------------
## M1 1.000 1.000 1.000
csLC$tt
##
## OUT: output value
## n: number of cases in configuration
## incl: sufficiency inclusion score
## PRI: proportional reduction in inconsistency
##
## DEV URB LIT IND STB OUT n incl PRI cases
## 1 0 0 0 0 0 0 3 0.000 0.000 GR,PT,ES
## 2 0 0 0 0 1 0 2 0.000 0.000 IT,RO
## 5 0 0 1 0 0 0 2 0.000 0.000 HU,PL
## 6 0 0 1 0 1 0 1 0.000 0.000 EE
## 22 1 0 1 0 1 1 2 1.000 1.000 FI,IE
## 23 1 0 1 1 0 0 1 0.000 0.000 AU
## 24 1 0 1 1 1 1 2 1.000 1.000 FR,SE
## 31 1 1 1 1 0 0 1 0.000 0.000 DE
## 32 1 1 1 1 1 1 4 1.000 1.000 BE,CZ,NL,UK
csLC$PIchart
##
## 22 24 32
## DEV*~URB*LIT*STB x x -
## DEV*LIT*IND*STB - x x
csLC %>% venn()
LM %>%
truthTable("SURV", show.cases = TRUE) %>%
minimize(details = TRUE)
##
## M1: DEV[2]*LIT[1]*IND[1]*STB[1] + DEV[1]*URB[0]*LIT[1]*IND[0]*STB[1] +
## DEV[1]*URB[1]*LIT[1]*IND[1]*STB[1] <-> SURV[1]
##
## inclS PRI covS covU cases
## ----------------------------------------------------------------------------------
## 1 DEV[2]*LIT[1]*IND[1]*STB[1] 1.000 1.000 0.625 0.625 FR,SE; BE,NL,UK
## 2 DEV[1]*URB[0]*LIT[1]*IND[0]*STB[1] 1.000 1.000 0.250 0.250 FI,IE
## 3 DEV[1]*URB[1]*LIT[1]*IND[1]*STB[1] 1.000 1.000 0.125 0.125 CZ
## ----------------------------------------------------------------------------------
## M1 1.000 1.000 1.000
LF %>%
truthTable("SURV", incl.cut = 0.7, show.cases = TRUE) -> ttLF
ttLF
##
## OUT: output value
## n: number of cases in configuration
## incl: sufficiency inclusion score
## PRI: proportional reduction in inconsistency
##
## DEV URB LIT IND STB OUT n incl PRI cases
## 1 0 0 0 0 0 0 3 0.216 0.000 GR,PT,ES
## 2 0 0 0 0 1 0 2 0.278 0.000 IT,RO
## 5 0 0 1 0 0 0 2 0.521 0.113 HU,PL
## 6 0 0 1 0 1 0 1 0.529 0.228 EE
## 22 1 0 1 0 1 1 2 0.804 0.719 FI,IE
## 23 1 0 1 1 0 0 1 0.378 0.040 AU
## 24 1 0 1 1 1 1 2 0.709 0.634 FR,SE
## 31 1 1 1 1 0 0 1 0.445 0.050 DE
## 32 1 1 1 1 1 1 4 0.904 0.886 BE,CZ,NL,UK
Membership values of cases for existing rows
ttLF$minmat
## 1 2 5 6 22 23 24 31 32
## AU 0.01 0.01 0.19 0.19 0.27 0.57 0.43 0.12 0.12
## BE 0.00 0.00 0.00 0.00 0.00 0.02 0.11 0.02 0.89
## CZ 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.09 0.58
## EE 0.02 0.02 0.09 0.84 0.16 0.01 0.01 0.01 0.01
## FI 0.01 0.01 0.42 0.42 0.58 0.08 0.08 0.03 0.03
## FR 0.01 0.01 0.02 0.02 0.19 0.05 0.81 0.03 0.03
## DE 0.01 0.01 0.04 0.04 0.04 0.21 0.21 0.69 0.31
## GR 0.57 0.43 0.13 0.13 0.04 0.04 0.04 0.04 0.04
## HU 0.12 0.12 0.84 0.13 0.07 0.07 0.07 0.07 0.07
## IE 0.02 0.02 0.05 0.28 0.72 0.01 0.01 0.01 0.01
## IT 0.42 0.53 0.41 0.41 0.34 0.34 0.34 0.10 0.10
## NL 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.01 0.94
## PL 0.41 0.00 0.59 0.00 0.00 0.00 0.00 0.00 0.00
## PT 0.89 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01
## RO 0.16 0.83 0.16 0.17 0.01 0.00 0.00 0.00 0.00
## ES 0.70 0.20 0.09 0.09 0.03 0.03 0.03 0.03 0.03
## SE 0.01 0.01 0.05 0.05 0.33 0.09 0.67 0.09 0.13
## UK 0.00 0.00 0.00 0.00 0.00 0.01 0.01 0.02 0.98
ttLF %>% minimize(details = TRUE) -> csLF
csLF
##
## M1: DEV*~URB*LIT*STB + DEV*LIT*IND*STB -> SURV
##
## inclS PRI covS covU cases
## -------------------------------------------------------------------
## 1 DEV*~URB*LIT*STB 0.809 0.761 0.433 0.196 FI,IE; FR,SE
## 2 DEV*LIT*IND*STB 0.843 0.821 0.622 0.385 FR,SE; BE,CZ,NL,UK
## -------------------------------------------------------------------
## M1 0.871 0.851 0.818
csLF %>% venn()
ttLF %>% minimize(details = TRUE, include = "?") -> psLF
psLF
##
## M1: DEV*STB -> SURV
##
## inclS PRI covS covU cases
## -----------------------------------------------------------------
## 1 DEV*STB 0.869 0.848 0.824 - FI,IE; FR,SE; BE,CZ,NL,UK
## -----------------------------------------------------------------
## M1 0.869 0.848 0.824
psLF$solution[[1]] %>% venn(snames = "DEV, URB, LIT, IND, STB")
Simplyfying assumptions
psLF$SA
## $M1
## DEV URB LIT IND STB
## 18 1 0 0 0 1
## 20 1 0 0 1 1
## 26 1 1 0 0 1
## 28 1 1 0 1 1
## 30 1 1 1 0 1
Intermediate solution with direction expectaion. For example, if the existence of condition A is expected, it is employed as one of the simplifying assumption only if the logical reminder with existing condition A can be used for simplification of a term. See Dusa (2024, 8.7)
ttLF %>%
minimize(details = TRUE, include = "?",
dir.exp = "DEV, URB, LIT, IND, STB") -> isLF
isLF
##
## From C1P1:
##
## M1: DEV*LIT*STB -> SURV
##
## inclS PRI covS covU cases
## ---------------------------------------------------------------------
## 1 DEV*LIT*STB 0.869 0.848 0.824 - FI,IE; FR,SE; BE,CZ,NL,UK
## ---------------------------------------------------------------------
## M1 0.869 0.848 0.824
isLF$i.sol$C1P1$solution[[1]] %>% venn(snames = "DEV, URB, LIT, IND, STB")
Employed easy counterfacts which meets the expectation.
isLF$i.sol$C1P1$EC
## DEV URB LIT IND STB
## 30 1 1 1 0 1