---
title: "Migrating from PanelSelect 1.0.1 to 2.0.0"
output:
rmarkdown::html_vignette:
css:
- !expr system.file("rmarkdown", "templates", "html_vignette", "resources", "vignette.css", package = "rmarkdown")
- guide.css
vignette: >
%\VignetteIndexEntry{Migrating from PanelSelect 1.0.1 to 2.0.0}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(PanelSelect)
```
The main change is one fitting function, `panel_select()`, with common controls
and standard fitted-object methods. This guide maps the four panel-selection
functions in 1.0.1 to version 2.0.0 and highlights changes that can affect results.
Refit saved 1.0.1 analyses from their original data. Their result lists are not
current `panelselect` objects and cannot be passed directly to the new methods.
## 1. Update the fitting call {#function-map}
::: {.table-scroll tabindex="0" role="region" aria-label="Fitting function changes"}
| Outcome | Function in 1.0.1 | Current `panel_select()` family |
|:---|:---|:---|
| Linear | `probitRE_linearRE()` | `"linear"` |
| Binary | `probitRE_probitRE()` | `"probit"` |
| Poisson | `probitRE_PoissonRE()` | `"poisson"` |
| Poisson-lognormal | `probitRE_PLNRE()` | `"pln"` |
Table: Table 1. Replace model-specific functions with one fitting interface
:::
The **outcome formula now comes first**, followed by selection, data, ID and
family. Named arguments avoid mistakes when translating old positional calls.
For example, using `dat` from the [main vignette](vignette.html#fit):
```{r old-call, eval=FALSE}
# PanelSelect 1.0.1
old = probitRE_linearRE(d ~ x + w, y ~ x + w, id.name = "id", data = dat)
```
```{r current-call, eval=FALSE}
# PanelSelect 2.0.0
fit = panel_select(
outcome = y ~ x + w,
selection = d ~ x + w,
data = dat,
id = "id",
family = "linear")
summary(fit)
```
The same interface also fits cross-sectional Linear, binary and PLN selection
models with `id = NULL`, and standalone panel probit, Poisson and PLN models
with `selection = NULL`. Keep unselected rows in selection models; their outcome
may be `NA`.
## 2. Translate settings and parameter names {#argument-map}
::: {.table-scroll tabindex="0" role="region" aria-label="Argument and control changes"}
| Setting in 1.0.1 | Current equivalent |
|:---|:---|
| `id.name = "id"` | `id = "id"` |
| `rho_off = TRUE` (Linear/binary); `disable_rho = TRUE` (PLN) | `fixed = c(cor_re = 0)` |
| `tau_off = TRUE` (Linear/binary); `disable_tau = TRUE` (PLN) | `fixed = c(cor_error = 0)` |
| `rho.init`, `tau.init`, or supplied parameter values | Named natural-scale values in `start`, using Table 3 |
| `H` (Linear/binary) | `control = panel_control(quadrature = "gh", nodes = H)` |
| `method`, `reltol`, `factr`, `verbose` | Arguments of `panel_control()`; use `trace` instead of `verbose` |
| `use.optim = FALSE` (Linear/binary default) | `control = panel_control(optimizer = "maxLik")`; the current default is `optim()` with BFGS |
| `se_type = "BHHH"` or `"Hessian"` (count models) | `vcov = "opg"` or `vcov = "observed"` |
| Count-model `offset_w_name`, `offset_x_name` | `offset()` terms in the selection and outcome formulas |
Table: Table 2. Common argument and control changes
:::
For count models, old `H = c(h1, h2)` becomes
`nodes = c(selection = h2, outcome = h1)`. PLN also uses
`observation_nodes = h2`. This preserves the intended orders, not identical
numerical results. The current defaults are fixed GH with 10 nodes per person
effect and 20 nodes for PLN's separate observation integral.
::: {.table-scroll tabindex="0" role="region" aria-label="Parameter name changes"}
| Parameter | 1.0.1 Linear/binary | 1.0.1 count models | Current name |
|:---|:---|:---|:---|
| Selection coefficients | `probit.` or `probit1.` | Selection-equation column names | `selection.` |
| Outcome coefficients | `linear.` or `probit2.` | Outcome-equation column names | `outcome.` |
| Selection person-effect SD | `delta` | `delta` | `sd_re_selection` |
| Outcome person-effect SD | `lambda` | `sigma` | `sd_re_outcome` |
| Linear residual / PLN occasion SD | `sigma` (Linear) | `gamma` (PLN) | `sd_error` |
| Person-effect correlation | `rho` | `rho` | `cor_re` |
| Occasion-error correlation | `tau` | `tau` (PLN) | `cor_error` |
Table: Table 3. Names used by coefficients, starting values and restrictions
:::
`start` accepts any subset of the current names; `init` supplies the rest.
`fixed` holds named parameters at their supplied values. Supply natural-scale
values, not optimizer coordinates. Free SDs must start positive; fixed SDs may
be zero where allowed. Correlations must lie strictly between −1 and 1.
The Linear/binary functions in 1.0.1 ignored `par`; current `start` values are
honored. When transferring estimates, use the old `estimates` table and map its
names explicitly. Do not copy raw `$par` or `$estimate` indiscriminately: their
scales differed across the old functions.
## 3. Read results through methods {#output-map}
::: {.table-scroll tabindex="0" role="region" aria-label="Result extraction changes"}
| Result in 1.0.1 | Current method |
|:---|:---|
| `$estimates[, "estimate"]` | `coef(fit)` |
| `$estimates` | `summary(fit)$coefficients`; `confint(fit)` for intervals |
| `$var`, `$var_bhhh`, `$var_hessian`, `$se` | `vcov(fit)`; SEs in `summary(fit)$coefficients[, "se"]` |
| `$LL`, `$maximum`, `$value` | `logLik(fit)` |
| `$AIC`, `$BIC` | `AIC(fit)`; use `BIC(fit, unit = "observations")` for the old row-count convention |
| `$predict$respond_prob`, `$predict$prob` | `predict(fit, newdata, type = "selection_probability")` |
| `$predict$outcome`, `$predict$outcome_prob` | `predict(fit, newdata, type = "response")` |
| `$predict$actual_outcome` | `predict(fit, newdata, type = "joint")` |
| `$predict$pop_mean` | `predict(fit, newdata, type = "response", aggregate = TRUE)` |
Table: Table 4. Replace direct component access with fitted-object methods
:::
Predictions are requested after fitting; add `se.fit = TRUE` for their standard
errors. `type = "response"` is the potential-outcome mean, while
`type = "selected_mean"` is the mean among selected observations. Population
predictions remain the default. `type = "joint"` gives the mean observed
contribution, counting unselected outcomes as zero. History-conditioned predictions require explicit
`history` data and GH/AGH at the applicable integration levels.
`BIC(fit)` now counts independent panels by default. For covariance alternatives,
request `vcov(fit, type = "observed")` or `vcov(fit, type = "opg")` explicitly.
## 4. Understand changes in results {#why-numbers-can-differ}
Matching formulas and integration orders does not guarantee the same estimates
or standard errors as 1.0.1. The main reasons are:
- **Starting values.** The current default uses separate random-effects models
for panel selection. The old Linear/binary default used pooled regressions;
choose `init = "pooled"` to use that approach. The old count models already
used random-effects auxiliaries.
- **Standard errors.** The default is now `vcov = "opg"`, based on independent-unit
score outer products. The old Linear/binary functions preferred the inverse
Hessian; choose `vcov = "observed"` to request observed information. Invalid
requested covariance remains unavailable rather than being replaced silently.
- **Corrected calculations.** Fixes to derivatives, parameter transformations and
rare-probability calculations can change estimates or standard errors. Formula
`offset()` terms ignored by the old Linear/binary functions now enter their
predictors with coefficient one.
- **Numerical accuracy.** Adaptive GH and GL provide alternatives to fixed GH.
Use `check_stationarity()` and `check_quadrature()` to assess a new fit, and
compare estimates under common, checked settings. Convergence alone does not
establish integration accuracy or a global maximum.
See the [main vignette](vignette.html#integration-choices) for a short checking
workflow, and the [fitting](../html/panel_select.html),
[control](../html/panel_control.html) and
[prediction](../html/predict.panelselect.html) help for additional options.