Dear spatstat developers, I created this issue to report a problematic interaction between spatstat.model and splines when the underlying mppm object was defined using a natural cubic spline. For example:
library(spatstat)
library(splines)
H <- hyperframe(Y = waterstriders)
obj <- mppm(Y ~ ns(x, df = 3), data=H)
subfits(obj)
#> Error in `ns()`: ! all interior knots match left boundary knot
Created on 2026-02-05 with reprex v2.1.1.9000
After some simple debugging, I noticed that the error occurs in spatstat.model::impliedpresence() when running model.frame(). Based on my understanding, it seems that impliedpresence() tries to build a "fake" model matrix row-by-row starting from a matrix of all zeros. Moreover, I run a few more tests and noticed that exactly the same error occurs when running analogous code outside of spatstat, for example:
library(splines)
toy <- data.frame(x = 0)
model.frame(~ ns(x, df = 3), data = toy)
#> Error in `ns()`: ! all interior knots match left boundary knot
Created on 2026-02-05 with reprex v2.1.1.9000
Do you have any suggestion on how to proceed? Thanks!
Session info
sessioninfo::session_info()
#> Warning in system2("quarto", "-V", stdout = TRUE, env = paste0("TMPDIR=", :
#> running command '"quarto"
#> TMPDIR=C:/Users/andre/AppData/Local/Temp/Rtmp6xPOc8/file55d0bb173aa -V' had
#> status 1
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.4.2 (2024-10-31 ucrt)
#> os Windows 11 x64 (build 26200)
#> system x86_64, mingw32
#> ui RTerm
#> language (EN)
#> collate Italian_Italy.utf8
#> ctype Italian_Italy.utf8
#> tz Europe/Rome
#> date 2026-02-05
#> pandoc 3.2 @ C:/Program Files/RStudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
#> quarto NA @ C:\\Users\\andre\\AppData\\Local\\Programs\\Quarto\\bin\\quarto.exe
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> abind 1.4-8 2024-09-12 [1] CRAN (R 4.4.2)
#> cli 3.6.5 2025-04-23 [1] CRAN (R 4.4.2)
#> deldir 2.0-4 2024-02-28 [1] CRAN (R 4.4.2)
#> digest 0.6.37 2024-08-19 [1] CRAN (R 4.4.2)
#> evaluate 1.0.3 2025-01-10 [1] CRAN (R 4.4.2)
#> fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.4.2)
#> fs 1.6.5 2024-10-30 [1] CRAN (R 4.4.2)
#> glue 1.8.0 2024-09-30 [1] CRAN (R 4.4.2)
#> goftest 1.2-3 2021-10-07 [1] CRAN (R 4.4.2)
#> htmltools 0.5.8.1 2024-04-04 [1] CRAN (R 4.4.2)
#> knitr 1.50.4 2025-07-11 [1] https://yihui.r-universe.dev (R 4.4.2)
#> lattice 0.22-6 2024-03-20 [2] CRAN (R 4.4.2)
#> lifecycle 1.0.4 2023-11-07 [1] CRAN (R 4.4.2)
#> Matrix 1.7-1 2024-10-18 [2] CRAN (R 4.4.2)
#> mgcv 1.9-3 2025-04-04 [1] CRAN (R 4.4.2)
#> nlme * 3.1-166 2024-08-14 [2] CRAN (R 4.4.2)
#> pillar 1.10.2 2025-04-05 [1] CRAN (R 4.4.3)
#> polyclip 1.10-7 2024-07-23 [1] CRAN (R 4.4.2)
#> reprex 2.1.1.9000 2025-02-25 [1] Github (tidyverse/reprex@07cd5d7)
#> rlang 1.1.6 2025-04-11 [1] CRAN (R 4.4.3)
#> rmarkdown 2.29 2024-11-04 [1] CRAN (R 4.4.2)
#> rpart * 4.1.23 2023-12-05 [2] CRAN (R 4.4.2)
#> rstudioapi 0.17.1 2024-10-22 [1] CRAN (R 4.4.2)
#> sessioninfo 1.2.3 2025-02-05 [1] CRAN (R 4.4.2)
#> spatstat * 3.5-1 2026-02-01 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.data * 3.1-9 2025-10-18 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.explore * 3.7-0.002 2026-02-03 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.geom * 3.7-0 2026-01-20 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.linnet * 3.4-1 2026-01-31 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.model * 3.6-1 2026-01-29 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.random * 3.4-4 2026-01-21 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.sparse 3.1-0 2024-06-21 [1] CRAN (R 4.4.2)
#> spatstat.univar * 3.1-6.002 2026-02-03 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> spatstat.utils 3.2-1 2026-01-08 [1] https://spatstat.r-universe.dev (R 4.4.2)
#> tensor 1.5 2012-05-05 [1] CRAN (R 4.4.2)
#> vctrs 0.6.5 2023-12-01 [1] CRAN (R 4.4.2)
#> withr 3.0.2 2024-10-28 [1] CRAN (R 4.4.2)
#> xfun 0.52 2025-04-02 [1] CRAN (R 4.4.2)
#> yaml 2.3.10 2024-07-26 [1] CRAN (R 4.4.2)
#>
#> [1] C:/Users/andre/AppData/Local/R/win-library/4.4
#> [2] C:/Program Files/R/R-4.4.2/library
#> * ── Packages attached to the search path.
#>
#> ──────────────────────────────────────────────────────────────────────────────
Dear spatstat developers, I created this issue to report a problematic interaction between
spatstat.modelandsplineswhen the underlyingmppmobject was defined using a natural cubic spline. For example:Created on 2026-02-05 with reprex v2.1.1.9000
After some simple debugging, I noticed that the error occurs in
spatstat.model::impliedpresence()when runningmodel.frame(). Based on my understanding, it seems thatimpliedpresence()tries to build a "fake" model matrix row-by-row starting from a matrix of all zeros. Moreover, I run a few more tests and noticed that exactly the same error occurs when running analogous code outside ofspatstat, for example:Created on 2026-02-05 with reprex v2.1.1.9000
Do you have any suggestion on how to proceed? Thanks!
Session info