Skip to contents

Grow a binary tree by directly maximizing concentration-index gain across all candidate variables and split points at each node, while storing the result as a standard partykit::party() object.

ctree_ci() is kept for existing code. New code should use ci_tree(), because the current tree-growing method is greedy concentration-index splitting rather than conditional-inference splitting.

Usage

ci_tree(
  formula,
  data,
  rank_name,
  outcome_name,
  weights = NULL,
  type = c("CI", "CIg", "CIc", "L"),
  control = ci_tree_control(),
  na.action = stats::na.omit,
  ...
)

ctree_ci(...)

Arguments

formula

A model formula, typically with a two-column response such as cbind(rank, outcome) ~ x1 + x2.

data

A data frame containing the variables in formula.

rank_name

Name of the socioeconomic rank variable.

outcome_name

Name of the outcome variable.

weights

Optional non-negative numeric case weights.

type

One of "CI", "CIg", "CIc", or "L" selecting the inequality index used for split scoring. "L" uses observed socioeconomic levels in the first response column rather than fractional ranks.

control

A control object created by ci_tree_control(). Objects from partykit::ctree_control() are also accepted for shared controls such as minsplit, minbucket, minprob, maxdepth, and mtry.

na.action

A function for handling missing values.

...

Currently ignored; retained for backwards compatibility.

Value

A fitted ci_tree object inheriting from constparty and party.

A fitted ci_tree object inheriting from constparty and party.

Details

This helper is intended for inequality-aware tree fitting where the response contains a socioeconomic ranking variable and a health outcome. Unlike partykit::ctree(), it does not use conditional-inference tests for first-stage variable selection.

At each non-terminal node t, ci_tree() searches across all candidate variables and all admissible split points, then selects the pair with the largest concentration-index gain: $$(j^*, s^*) = \arg\max_{j \in \mathcal{J}_t,\ s \in \mathcal{S}_{jt}} G_m(t, j, s).$$ The gain G_m is computed by weighted_ci_gain() from the selected concentration-index impurity m, one of "CI", "CIg", "CIc", or "L".

The fitted object uses partykit::party() for storage, traversal, prediction, and plotting, but the tree-growing rule is the package's greedy concentration-index rule rather than the conditional-inference test-based rule used by partykit::ctree().

Stopping rules operate in three places. First, a node is searched only when it satisfies minsplit and has not reached maxdepth. Second, candidate splits are admissible only when both child nodes satisfy minbucket and minprob. Third, after all admissible splits are scored, the best split is accepted only when its gain is finite and greater than min_gain. If min_relative_gain is positive, the split must also recover at least that share of the parent-node impurity.

References

Breiman L, Friedman JH, Olshen RA, Stone CJ (1984). Classification and Regression Trees. Wadsworth.

Hothorn T, Zeileis A (2015). "partykit: A Modular Toolkit for Recursive Partytioning in R." Journal of Machine Learning Research, 16, 3905-3909. https://jmlr.org/papers/v16/hothorn15a.html.

Wagstaff A, van Doorslaer E, Watanabe N (2003). "On Decomposing the Causes of Health Sector Inequalities with an Application to Malnutrition Inequalities in Vietnam." Journal of Econometrics, 112(1), 207-223. doi:10.1016/S0304-4076(02)00161-6.

Examples

data(kenya, package = "ineqTrees")

kenya_model_vars <- c(
  "wealth",
  "deadu5_num",
  "rural",
  "ed",
  "reg",
  "unskilled"
)

kenya_model_data <- kenya[
  stats::complete.cases(kenya[, kenya_model_vars]),
  kenya_model_vars
]

set.seed(20260512)
kenya_model_data <- kenya_model_data[
  sample.int(nrow(kenya_model_data), 800L),
  ,
  drop = FALSE
]

fit <- ci_tree(
  formula = cbind(wealth, deadu5_num) ~ rural + ed + reg + unskilled,
  data = kenya_model_data,
  rank_name = "wealth",
  outcome_name = "deadu5_num",
  control = ci_tree_control(
    minsplit = 100,
    minbucket = 50,
    minprob = 0.05,
    maxdepth = 3
  )
)

fit
#> Greedy concentration-index tree
#> 
#> Formula:
#>   cbind(wealth, deadu5_num) ~ rural + ed + reg + unskilled
#> 
#> Criterion: CI
#> Observations: 800
#> Inner nodes: 5
#> Terminal nodes: 6
#> Max depth: 3
#> 
#> Root node:
#>   mean outcome = 7.2%
#>   CI = 0.413
#> 
#> Terminal node summary (highest criterion first):
#>  node   n weight depth    CI outcome_mean outcome_percent
#>     9 209    209     3 0.322        0.048             4.8
#>    10 127    127     3 0.285        0.157            15.7
#>    11  86     86     2 0.147        0.244            24.4
#>     6 137    137     2 0.011        0.029             2.9
#>     5 132    132     3 0.003        0.023             2.3
#>     4 109    109     3 0.000        0.000             0.0
#>                                                                                                                                                                                                                                                                                                                                                                                                                                                                 rule
#>   reg in {Mombasa, Kwale, Kilifi, Tana River, Wajir, Mandera, Marsabit, Tharaka-Nithi, Embu, Makueni, Kiambu, Turkana, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Homa Bay, Kisii, Nyamira} & reg in {Mombasa, Kwale, Kilifi, Tharaka-Nithi, Embu, Makueni, Kiambu, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Kisii, Nyamira} & unskilled in {No}
#>  reg in {Mombasa, Kwale, Kilifi, Tana River, Wajir, Mandera, Marsabit, Tharaka-Nithi, Embu, Makueni, Kiambu, Turkana, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Homa Bay, Kisii, Nyamira} & reg in {Mombasa, Kwale, Kilifi, Tharaka-Nithi, Embu, Makueni, Kiambu, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Kisii, Nyamira} & unskilled in {Yes}
#>                                                                                                                                                reg in {Mombasa, Kwale, Kilifi, Tana River, Wajir, Mandera, Marsabit, Tharaka-Nithi, Embu, Makueni, Kiambu, Turkana, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Homa Bay, Kisii, Nyamira} & reg in {Tana River, Wajir, Mandera, Marsabit, Turkana, Homa Bay}
#>                                                                                                                                                                                                                                      reg in {Lamu, Taita Taveta, Garissa, Isiolo, Meru, Kitui, Machakos, Nyandarua, Nyeri, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi} & unskilled in {Yes}
#>                                                                                                                                             reg in {Lamu, Taita Taveta, Garissa, Isiolo, Meru, Kitui, Machakos, Nyandarua, Nyeri, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi} & unskilled in {No} & reg in {Meru, Nyeri, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi}
#>                                                                                                          reg in {Lamu, Taita Taveta, Garissa, Isiolo, Meru, Kitui, Machakos, Nyandarua, Nyeri, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi} & unskilled in {No} & reg in {Lamu, Taita Taveta, Garissa, Isiolo, Kitui, Machakos, Nyandarua, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo}
ci_tree_terminal_summary(fit)
#>     node     n weight depth          ci outcome_mean outcome_percent
#>    <int> <int>  <num> <int>       <num>        <num>           <num>
#> 1:     4   109    109     3 0.000000000   0.00000000        0.000000
#> 2:     5   132    132     3 0.002525253   0.02272727        2.272727
#> 3:     6   137    137     2 0.010948905   0.02919708        2.919708
#> 4:     9   209    209     3 0.321531100   0.04784689        4.784689
#> 5:    10   127    127     3 0.285039370   0.15748031       15.748031
#> 6:    11    86     86     2 0.146733112   0.24418605       24.418605
#>                                                                                                                                                                                                                                                                                                                                                                                                                                                                   rule
#>                                                                                                                                                                                                                                                                                                                                                                                                                                                                 <char>
#> 1:                                                                                                         reg in {Lamu, Taita Taveta, Garissa, Isiolo, Meru, Kitui, Machakos, Nyandarua, Nyeri, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi} & unskilled in {No} & reg in {Lamu, Taita Taveta, Garissa, Isiolo, Kitui, Machakos, Nyandarua, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo}
#> 2:                                                                                                                                            reg in {Lamu, Taita Taveta, Garissa, Isiolo, Meru, Kitui, Machakos, Nyandarua, Nyeri, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi} & unskilled in {No} & reg in {Meru, Nyeri, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi}
#> 3:                                                                                                                                                                                                                                     reg in {Lamu, Taita Taveta, Garissa, Isiolo, Meru, Kitui, Machakos, Nyandarua, Nyeri, Kirinyaga, Murang'a, Trans Nzoia, Nandi, Baringo, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi} & unskilled in {Yes}
#> 4:  reg in {Mombasa, Kwale, Kilifi, Tana River, Wajir, Mandera, Marsabit, Tharaka-Nithi, Embu, Makueni, Kiambu, Turkana, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Homa Bay, Kisii, Nyamira} & reg in {Mombasa, Kwale, Kilifi, Tharaka-Nithi, Embu, Makueni, Kiambu, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Kisii, Nyamira} & unskilled in {No}
#> 5: reg in {Mombasa, Kwale, Kilifi, Tana River, Wajir, Mandera, Marsabit, Tharaka-Nithi, Embu, Makueni, Kiambu, Turkana, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Homa Bay, Kisii, Nyamira} & reg in {Mombasa, Kwale, Kilifi, Tharaka-Nithi, Embu, Makueni, Kiambu, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Kisii, Nyamira} & unskilled in {Yes}
#> 6:                                                                                                                                               reg in {Mombasa, Kwale, Kilifi, Tana River, Wajir, Mandera, Marsabit, Tharaka-Nithi, Embu, Makueni, Kiambu, Turkana, West Pokot, Samburu, Uasin Gishu, Elgeyo-Marakwet, Narok, Kericho, Bomet, Kakamega, Bungoma, Siaya, Homa Bay, Kisii, Nyamira} & reg in {Tana River, Wajir, Mandera, Marsabit, Turkana, Homa Bay}