---
title: "Data preparation"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Data preparation}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.align = "center", out.width = "100%")
knitr::opts_chunk$set(comment = "#>")
old_options <- options(width = 100)
```

`spifa()` expects data in a specific shape: one row per respondent, and the binary item
responses stored as a single *matrix-valued column* (`nobs x nitems`) rather than one
column per item. This is the same convention base R uses for multivariate `lm()`. This
vignette builds a small dataset acceptable by `spifa()`.

```{r}
library(spifa)
library(sf)
```

## Simulating a raw questionnaire

Five binary items, a household `wealth` covariate, and GPS coordinates, for 20 households:

```{r}
set.seed(1)
nobs <- 20
nitems <- 5

raw <- data.frame(
  id = seq_len(nobs),
  wealth = rnorm(nobs),
  lon = runif(nobs, -71.70, -71.68),
  lat = runif(nobs, -7.06, -7.04),
  item1 = rbinom(nobs, 1, 0.1) == 1,
  item2 = rbinom(nobs, 1, 0.2) == 1,
  item3 = rbinom(nobs, 1, 0.3) == 1,
  item4 = rbinom(nobs, 1, 0.4) == 1,
  item5 = rbinom(nobs, 1, 0.5) == 1
)
raw
```

## Data for `spifa()`

We extract the item as a matrix, and then provide it to a new `data.frame` to later
convert to `sf`:

```{r}
# get items as a matrix
items <- subset(raw, select = grep("^item", names(raw))) |>
  as.matrix() |>
  unname()
# create data.frame and geo-reference it
data <- data.frame(items = I(items), wealth = raw$wealth, x = raw$lon, y = raw$lat) |>
    st_as_sf(coords = c("x", "y"), crs = 4326)
data
```

Notice that we can easily access the response `items`:

```{r}
data$items
```

This dataset can directly be used to fit a model:

```{r}
spifa(items ~ wealth, data = data, nfactors = 2, niter = 5)
```

Alternatively, you could also create the `sf` data first and then assign the items:

```{r}
data <- data.frame(wealth = raw$wealth, x = raw$lon, y = raw$lat) |>
    st_as_sf(coords = c("x", "y"), crs = 4326)
data$items <- items
data
```

```{r}
spifa(items ~ wealth, data = data, nfactors = 2, niter = 5)
```

## Missing values

### Missing item responses

Individual missing item responses (`NA`) don't need to be dropped or
imputed -- `spifa()` handles them natively, treating a missing response as
an unobserved auxiliary variable to be sampled along with everything else,
rather than requiring complete rows:

```{r}
data_na <- data
data_na$items[1:5, 1] <- NA

fit_na <- spifa(items ~ 1, data = data_na, nfactors = 2, ngp = 0, niter = 5)
fit_na
```

As you can see in `Dimensions`, the missing responses are not removed but rather
modelled.

### Missing predictor values

Missing *predictor* values behave differently, and are worth calling out:
a `NA` in a predictor column drops that respondent from the whole fit:

```{r}
data_na <- data
data_na$wealth[1:5] <- NA

fit_na <- spifa(items ~ wealth, data = data_na, nfactors = 2, ngp = 0, niter = 5)
fit_na
```

As you can see in `Dimensions`, the 5 respondents with a missing `wealth` value are
dropped -- 15 respondents remain, unlike the item-response case above.

```{r, include = FALSE}
options(old_options)
```

