Skip to contents

Tree and forest model wrappers

The examples in this article use the kenya child-level data shipped with ineqTrees. The fitted models use household wealth as the socioeconomic rank, under-five death as the outcome, and a small set of demographic predictors.

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
]

kenya_predictors <- c("rural", "ed", "reg", "unskilled")
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
]

splitfun <- ci_splitfun(
  rank_name = "wealth",
  outcome_name = "deadu5_num",
  type = "CI"
)

ctrl <- ci_tree_control(minsplit = 100, minbucket = 50, minprob = 0.05)

split <- splitfun(
  model = NULL,
  trafo = NULL,
  data = kenya_model_data,
  subset = seq_len(nrow(kenya_model_data)),
  weights = rep(1, nrow(kenya_model_data)),
  whichvar = match("reg", names(kenya_model_data)),
  ctrl = ctrl
)

partykit::character_split(split, kenya_model_data)
#> $name
#> [1] "reg"
#> 
#> $levels
#> [1] "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"                                        
#> [2] "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"
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 Tree size: 5 inner nodes, 6 terminal nodes, max depth 3

Terminal-node summary with subgroup rules
node n weight depth CI outcome_mean outcome_percent rule
9 209 209 3 0.322 0.048 4.8 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}
10 127 127 3 0.285 0.157 15.7 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}
11 86 86 2 0.147 0.244 24.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 {Tana River, Wajir, Mandera, Marsabit, Turkana, Homa Bay}
6 137 137 2 0.011 0.029 2.9 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}
5 132 132 3 0.003 0.023 2.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 {No} & reg in {Meru, Nyeri, Laikipia, Nakuru, Kajiado, Vihiga, Busia, Kisumu, Migori, Nairobi}
4 109 109 3 0.000 0.000 0.0 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}
data(kenya, package = "ineqTrees")

kenya_model_data <- kenya[
  stats::complete.cases(kenya[, "wealth", drop = FALSE]),
  "wealth",
  drop = FALSE
]

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

wealth_quintile <- cut(
  kenya_model_data$wealth,
  breaks = stats::quantile(
    kenya_model_data$wealth,
    probs = seq(0, 1, by = 0.2),
    na.rm = TRUE
  ),
  include.lowest = TRUE
)

quintile_weights <- as.numeric(table(wealth_quintile))
as_caseweights(quintile_weights, scale = 1000L)
#> [1] 200 200 200 200 200
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
]

set.seed(20260512)
forest_fit <- ci_forest(
  formula = cbind(wealth, deadu5_num) ~ rural + ed + reg + unskilled,
  data = kenya_model_data,
  rank_name = "wealth",
  outcome_name = "deadu5_num",
  ntree = 10L,
  mtry = 2L,
  control = ci_tree_control(
    minsplit = 100,
    minbucket = 50,
    minprob = 0.05,
    maxdepth = 3
  )
)

ci_forest_summary(forest_fit)
#>    ntree  mtry   type     n mean_outcome mean_prediction outcome_ci
#>    <int> <int> <char> <int>        <num>           <num>      <num>
#> 1:    10     2     CI   800       0.0725      0.07354455  0.4132759
#>    prediction_ci mean_terminal_nodes mean_max_depth
#>            <num>               <num>          <num>
#> 1:     0.1064643                 3.2            1.8
head(stats::predict(forest_fit, OOB = FALSE))
#> [1] 0.11454554 0.15889920 0.12928239 0.07539547 0.07130924 0.10565666