Skip to contents

Writes the product category columns, `approach1` to `approach3`, the `rd_approach*` columns, and the two person-level exclusion columns.

Usage

add_lmed_v20260902(
  skeleton,
  lmed,
  id_name = "lopnr",
  create_rd = TRUE,
  verbose = TRUE
)

Arguments

skeleton

A person-week `data.table` with `id` and `isoyearweek`. Weekly rows only. Where the skeleton comes from `swereg::create_skeleton()`, pass `skeleton[is_isoyear == FALSE]`. See Details.

lmed

A `data.table` of dispensed prescriptions.

id_name

The person identifier column of `lmed`.

create_rd

Logical. If `FALSE`, writes no `rd_approach*` column.

verbose

Logical. If `TRUE`, report progress with `message()`.

Value

`invisible(skeleton)`. Mutation is in place.

Details

The layer differs from `add_lmed_v20260828()` in one respect: a product gets its category from `inst/2023-mht/product_table_20260902.xlsx`, looked up on an exact normalised key, rather than from a prefix ladder. A delivered product with no row is an error.

It adds two columns that no earlier entry point wrote:

  • `ri_mht_excluded_product`, `TRUE` for every week of a person who ever held a product the table flags for removal

  • `ri_mht_excluded_reason`, the reason, or `NA`

**The function removes nobody.** It reports. Removing a person changes the cohort, and this layer owns columns of `skeleton`, never its rows.

Everything else is the 2026-08-28 behaviour, reached by calling that layer's own dated helpers rather than by copying them.

**`skeleton` MUST hold weekly rows only.** Each person MUST hold each of its ISO weeks once, consecutively, with no gap. A skeleton from `swereg::create_skeleton()` also carries one annual row per person per year, with `isoyearweek` such as `"1946-**"` and `is_isoyear` set to `TRUE`. An annual row is no ISO week. The function then stops with the error `skeleton$isoyearweek holds a value that is no ISO week: 1946-**`. Pass `skeleton[is_isoyear == FALSE]`, and fill the annual rows in the caller. That subset is a new `data.table`. The function writes its columns there, and the table the caller holds gets none of them.

Examples

library(data.table)

skeleton <- copy(fake_skeleton_mht)
lmed <- copy(fake_lmed_2026)

# Utrogestan takes a codebook rule keyed on strength, so it needs `lnmn`.
lmed[, lnmn := NA_character_]
#>      lopnr     produkt     edatum  fddd   lnmn
#>      <int>      <char>     <Date> <num> <char>
#>   1:     1     Divigel 2015-01-05    90   <NA>
#>   2:     1     Divigel 2015-03-30    90   <NA>
#>   3:     1     Divigel 2015-06-22    90   <NA>
#>   4:     1     Divigel 2015-09-14    90   <NA>
#>   5:     1     Divigel 2015-12-07    90   <NA>
#>  ---                                          
#> 124:    16     Divigel 2016-02-26    90   <NA>
#> 125:    16   Cerazette 2016-03-01    90   <NA>
#> 126:    17     Divigel 2015-01-07   -30   <NA>
#> 127:    17     Divigel 2015-03-31    90   <NA>
#> 128:    18 Paracetamol 2015-01-02    28   <NA>
lmed[produkt == "Utrogestan", lnmn := "Utrogestan, kapsel, mjuk 100 mg"]
#> Index: <produkt>
#>      lopnr     produkt     edatum  fddd   lnmn
#>      <int>      <char>     <Date> <num> <char>
#>   1:     1     Divigel 2015-01-05    90   <NA>
#>   2:     1     Divigel 2015-03-30    90   <NA>
#>   3:     1     Divigel 2015-06-22    90   <NA>
#>   4:     1     Divigel 2015-09-14    90   <NA>
#>   5:     1     Divigel 2015-12-07    90   <NA>
#>  ---                                          
#> 124:    16     Divigel 2016-02-26    90   <NA>
#> 125:    16   Cerazette 2016-03-01    90   <NA>
#> 126:    17     Divigel 2015-01-07   -30   <NA>
#> 127:    17     Divigel 2015-03-31    90   <NA>
#> 128:    18 Paracetamol 2015-01-02    28   <NA>

# The product table is built from the real deliveries, so it holds no row
# for a name that exists only in a fixture. `Paracetamol` is one: the
# register writes branded spellings such as `Paracetamol Kodein Evolan`.
# Dropping it changes no exposure, because it is not MHT either way.
lmed <- lmed[produkt != "Paracetamol"]

# the fixture holds one negative-duration row, which warns
skeleton <- suppressWarnings(
  add_lmed_v20260902(skeleton, lmed, verbose = FALSE)
)
skeleton[, .N, keyby = .(rd_approach1_single)]
#> Key: <rd_approach1_single>
#>    rd_approach1_single     N
#>                 <char> <int>
#> 1:             exclude  2727
#> 2:   local_or_none_mht  2027
#> 3:            previous   140
#> 4:        systemic_mht   717
#> 5:            tibolone     5
skeleton[, .N, keyby = .(ri_mht_excluded_product, ri_mht_excluded_reason)]
#> Key: <ri_mht_excluded_product, ri_mht_excluded_reason>
#>    ri_mht_excluded_product            ri_mht_excluded_reason     N
#>                     <lgcl>                            <char> <int>
#> 1:                   FALSE                              <NA>  5304
#> 2:                    TRUE possible gender-affirming therapy   312