Why Categorical Predictors Need Special Attention
A predictor such as policy channel may have values like “web,” “agent,” and “branch.” These labels identify groups; they do not have numerical distances or a natural order. A tree-based boosting implementation must still decide how to represent those groups when it searches for a split. The choice is not merely a data-storage detail: it can change which splits the algorithm considers and, in turn, the fitted trees.
In R, the correct preparation depends on the implementation and its version. The formula interface to gbm commonly expands factor predictors into indicator columns. Recent versions of xgboost can support categorical features natively when factors are supplied in a compatible data frame and categorical support is enabled. Other workflows, including older versions or numeric-matrix inputs, require explicit indicator encoding. Check the installed package’s documentation and the exact input type rather than assuming all boosting implementations handle factors alike.
How Common R Workflows Represent Categories
With the formula interface, gbm can accept a factor predictor in the data frame. Its formula processing represents categorical predictors through contrasts, typically using treatment contrasts: for a factor with \(K\) observed levels, the design matrix has \(K-1\) indicator columns when an intercept is included. The intercept is not a useful tree predictor, so formula processing handles the model matrix for fitting. In contrast, lower-level fitting interfaces expect numeric predictor inputs; prepare those inputs explicitly.
A typical formula workflow is:
For xgboost, recent R interfaces support categorical predictors with factors in a data-frame input when the data matrix is created with categorical support enabled. A common pattern is to create an xgb.DMatrix using enable_categorical = TRUE and fit with a compatible tree method, such as hist. A sparse matrix or a plain numeric matrix generally does not preserve factor metadata; in those workflows, create indicator columns instead. Native support and accepted input forms are version-dependent, so verify them for the installed release.
When using indicators, one common choice is treatment encoding: retain \(K-1\) columns and choose a reference level. Full one-hot encoding uses \(K\) columns, one for every level. Both can be useful for trees, but neither should be confused with assigning arbitrary integer labels. The key question is what split structures the representation permits.
Worked Example: Reading a Factor’s Indicator Columns
A hypothetical insurer records the acquisition channel for six policies, with levels “branch,” “agent,” and “web.” The factor’s level order is branch, agent, web. Show the treatment-coded columns and explain their interpretation. Method: use branch as the reference and create one binary column for each other level. This avoids treating the labels as numerical values.
For a row with channel “branch,” both indicators are zero. For “agent,” the agent indicator is one and the web indicator is zero. For “web,” the agent indicator is zero and the web indicator is one. The resulting rows are therefore:
| Channel | agent | web |
|---|---|---|
| branch | 0 | 0 |
| agent | 1 | 0 |
| web | 0 | 1 |
There are \(K=3\) levels, so treatment encoding produces \(K-1=2\) columns. A tree split on the agent column can separate agent from the other two groups. A split on the web column can separate web from the other two. The reference group is represented by zeros in both columns. Common mistake avoided: coding branch, agent, and web as 1, 2, and 3 would create numerical thresholds that imply an order these labels do not have.
Why Encoding Changes the Splits a Tree Can Use
For a numeric predictor, a standard tree split compares the feature with a threshold. For an indicator column, the useful split is usually zero versus one. A tree can combine such splits across levels, but the required tree structure may differ from a category-aware split that directly groups several levels together.
For squared-error regression, the split criterion can be understood through residual sums of squares. At a particular boosting step, let \(r_i\) be the current residual for observation \(i\). For a candidate split, calculate the mean residual in each child node and the sum of squared deviations from those child means. The reduction in residual sum of squares is the parent-node sum minus the two child-node sums. A larger reduction is preferable, before any implementation-specific penalties or constraints are applied.
A native categorical split may group a subset of levels against the remaining levels, subject to the implementation’s rules and regularization. Indicator encoding makes individual levels easy to isolate, while grouping several levels can require more than one split. Integer coding is riskier: a threshold on codes can only separate adjacent values in the arbitrary code order. It can therefore exclude a useful grouping entirely.
Worked Example: Arbitrary Integer Codes Restrict a Split
A hypothetical claim study has six observations. The nominal predictor is repair network, with levels A, B, and C. Their squared-error residuals at a boosting step are A: 0 and 2; B: 8 and 10; C: 1 and 3. Compare an ideal category grouping that separates B from A and C with the splits available if the levels are coded A = 1, B = 2, C = 3 and split at a numerical threshold. Method: calculate the residual sum of squares before and after each candidate split. Ignore regularization to isolate the encoding effect.
The overall residual mean is \((0+2+8+10+1+3)/6=24/6=4\). The parent sum of squares is \(16+4+16+36+9+1=82\).
A category-aware split that isolates B gives B a mean of \((8+10)/2=9\), with within-group sum \(1+1=2\). The other group has residuals 0, 2, 1, 3, mean \(6/4=1.5\), and sum \(2.25+0.25+0.25+2.25=5\). The child total is \(2+5=7\), so the reduction is \(82-7=75\).
With integer codes, the possible nontrivial threshold splits are A versus B,C, or A,B versus C. For the first, A has mean 1 and sum \(1+1=2\). B,C have mean \((8+10+1+3)/4=5.5\), and sum \(6.25+20.25+20.25+6.25=53\). The child total is 55 and the reduction is \(82-55=27\).
For the second threshold, A,B have mean 5 and sum \(25+9+9+25=68\); C has mean 2 and sum \(1+1=2\). The child total is 70 and the reduction is \(82-70=12\). Neither numeric threshold can produce the best grouping, B versus A,C, whose reduction was 75. Check: the largest reduction among the two code-based thresholds is 27, smaller than 75. Common mistake avoided: integer codes are not a harmless shortcut for a nominal factor.
Native Categorical Splits and Indicator Splits
Native categorical support can consider category groupings more directly than a single split on one indicator. The exact search is implementation-specific: some versions or settings use one-category-versus-rest splits at lower cardinality, while other cases can use category partitions. Controls such as category cardinality thresholds can influence the split strategy. Do not assume that every version evaluates every possible partition or will choose the same split as another implementation.
Indicator encoding remains a practical, widely applicable approach, particularly when the implementation requires numeric inputs. But the representation affects tree depth and the sequence of splits needed to express a category grouping. When interpreting fitted splits, report the encoding and reference level. Two models trained on the same rows can have different candidate splits simply because their categorical inputs were prepared differently.
Worked Example: Comparing a Grouped Split With One-Level Isolation
At a squared-error boosting step, a hypothetical service region has residuals A: 1 and 3; B: 7 and 9; C: 6 and 8; D: 2 and 4. Compare a category-aware split grouping A and D against B and C with the split that isolates A from all other levels. Method: use within-child residual sums of squares. This illustrates the candidate-split difference; actual software may apply additional constraints or penalties.
The parent mean is \((1+3+7+9+6+8+2+4)/8=40/8=5\). The parent sum of squares is \(16+4+4+16+1+9+9+1=60\).
For the grouping A,D versus B,C, the first child contains 1, 3, 2, 4 and has mean \(10/4=2.5\). Its sum is \(2.25+0.25+0.25+2.25=5\). The second child contains 7, 9, 6, 8 and has mean \(30/4=7.5\). Its sum is \(0.25+2.25+2.25+0.25=5\). The child total is 10, giving a reduction of \(60-10=50\).
If a split isolates A, its residuals 1 and 3 have mean 2 and sum \(1+1=2\). The remaining residuals 7, 9, 6, 8, 2, 4 have mean \(36/6=6\) and sum \(1+9+0+4+16+4=34\). The child total is 36 and the reduction is \(60-36=24\). The grouped split reduces the sum by 50, compared with 24 for isolating A. Check: each child sum is calculated around that child’s own mean. Common mistake avoided: assuming one indicator split can directly express every multi-level grouping.
R Preparation and Level Consistency
Whichever implementation is used, training and prediction data need a consistent categorical schema. In R, a factor stores its levels, and those levels can affect both the design matrix and the treatment reference. Establish the intended levels from the training design, then apply the same schema to validation and future data. Do not silently assign different integer codes or reference levels in separate data sets.
Confirm that it is nominal or ordinal, review observed values, and identify rare or misspelled labels before fitting.
Use a factor with a compatible native categorical workflow, or create indicators for numeric-only inputs. Preserve a deliberate reference level if using treatment contrasts.
Use the training levels and encoding rules for validation and prediction data. Decide explicitly how to handle a level that was not present in training.
Confirm whether the fitted function receives factors, a data frame, a dense matrix, or a sparse matrix; these can have different categorical behavior.
For example, converting a factor with as.numeric() returns its internal integer codes, not the displayed labels and not a set of indicators. If these codes are passed as a numeric predictor, the model may split on their arbitrary ordering. Similarly, an unseen prediction-time level should not be allowed to become an accidental missing value without a deliberate plan. A common solution is to combine rare or future categories into a training-defined “other” level before fitting, provided that this is substantively appropriate. Any such rule must be applied consistently.
These choices matter for actuarial prediction because categories often represent channels, product types, regions, or administrative groups. Encoding can affect which groupings a tree can express, how deep a tree must be to express them, and how predictions behave when data contain unfamiliar levels. A sound workflow records the package version, input type, factor levels, contrasts, and any category pooling used. This tutorial is aligned with the SOA Exam PA (Predictive Analytics) syllabus.
Check Your Understanding
For each question, identify the representation or split implication that matters.
- A predictor has five nominal levels and is treatment-encoded with the first level as reference. How many indicator columns are produced, and what pattern represents the reference level? (Answer: Four columns; the reference level is represented by all four indicators equal to zero.)
- A nominal variable has levels red, blue, and green, assigned codes 1, 2, and 3. Which two groupings can a single threshold split create, and can it directly create red and green versus blue? (Answer: It can create red versus blue-and-green, or red-and-blue versus green; it cannot directly create red-and-green versus blue.)
- A model is trained with factor levels web, agent, and branch. A prediction row has level mobile, which did not occur in training. What should be checked before prediction? (Answer: Apply an explicit, training-consistent unknown-level rule, such as mapping to a suitable pooled “other” level; do not allow a silent, unintended missing value or different coding.)
- You want native categorical handling in a recent xgboost R workflow. State the essential input and fitting checks. (Answer: Supply categorical factor columns in a compatible data-frame-based DMatrix with categorical support enabled, use a compatible tree method such as hist, and verify that the installed version supports that workflow.)
- At a squared-error boosting step, residuals are P: 0 and 2; Q: 4 and 6; R: 1 and 3. Find the parent sum of squares and the reduction from grouping P,R against Q. (Answer: Parent mean \(16/6=8/3\); parent sum of squares \(66-256/6=70/3\). The P,R child has mean 1.5 and sum 5; Q has mean 5 and sum 2. The child total is 7, so the reduction is \(70/3-7=49/3\), approximately 16.3333.)