35  ppp

Function spatstat.geom::ppp() (v3.7.0.6) creates a two-dimensional point-pattern object (ppp.object), i.e., an R object of S3 class 'ppp'. A point-pattern contains the \(x\)- and \(y\)-coordinates in an observation window (owin, Chapter 33) and may contain

The S3 generic function spatstat.geom::as.ppp() (v3.7.0.6) converts R objects of various classes into a point-pattern. Listing 35.1 summarizes the S3 methods for the generic function as.ppp() in the spatstat.* family of packages,

Listing 35.1: S3 methods spatstat.*::as.ppp.*
Code
suppressPackageStartupMessages(library(spatstat))
.S3methods(generic.function = 'as.ppp', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = grepl(pattern = '^spatstat\\.', x = from))
#                      visible             from generic  isS4
# as.ppp.data.frame       TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.default          TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.influence.ppm    TRUE   spatstat.model  as.ppp FALSE
# as.ppp.lpp              TRUE  spatstat.linnet  as.ppp FALSE
# as.ppp.matrix           TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.NAobject         TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.ppp              TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.psp              TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.quad             TRUE    spatstat.geom  as.ppp FALSE
# as.ppp.ssf              TRUE spatstat.explore  as.ppp FALSE

Listing 35.2 summarizes the S3 methods for the class 'ppp' in the spatstat.* family of packages,

Listing 35.2: S3 methods spatstat.*::*.ppp
Code
suppressPackageStartupMessages(library(spatstat))
.S3methods(class = 'ppp', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = grepl(pattern = '^spatstat\\.', x = from))
#                              visible             from                  generic  isS4
# [.ppp                           TRUE    spatstat.geom                        [ FALSE
# [<-.ppp                         TRUE    spatstat.geom                      [<- FALSE
# affine.ppp                      TRUE    spatstat.geom                   affine FALSE
# anyDuplicated.ppp               TRUE    spatstat.geom            anyDuplicated FALSE
# as.data.frame.ppp               TRUE    spatstat.geom            as.data.frame FALSE
# as.im.ppp                       TRUE    spatstat.geom                    as.im FALSE
# as.layered.ppp                  TRUE    spatstat.geom               as.layered FALSE
# as.owin.ppp                     TRUE    spatstat.geom                  as.owin FALSE
# as.ppp.ppp                      TRUE    spatstat.geom                   as.ppp FALSE
# auc.ppp                         TRUE spatstat.explore                      auc FALSE
# berman.test.ppp                 TRUE spatstat.explore              berman.test FALSE
# boundingbox.ppp                 TRUE    spatstat.geom              boundingbox FALSE
# boundingcentre.ppp              TRUE    spatstat.geom           boundingcentre FALSE
# boundingcircle.ppp              TRUE    spatstat.geom           boundingcircle FALSE
# boundingradius.ppp              TRUE    spatstat.geom           boundingradius FALSE
# bw.abram.ppp                    TRUE spatstat.explore                 bw.abram FALSE
# bw.relrisk.ppp                  TRUE spatstat.explore               bw.relrisk FALSE
# by.ppp                          TRUE    spatstat.geom                       by FALSE
# cdf.test.ppp                    TRUE spatstat.explore                 cdf.test FALSE
# circumradius.ppp                TRUE    spatstat.geom             circumradius FALSE
# closepairs.ppp                  TRUE    spatstat.geom               closepairs FALSE
# closing.ppp                     TRUE    spatstat.geom                  closing FALSE
# connected.ppp                   TRUE    spatstat.geom                connected FALSE
# coords.ppp                      TRUE    spatstat.geom                   coords FALSE
# coords<-.ppp                    TRUE    spatstat.geom                 coords<- FALSE
# crossdist.ppp                   TRUE    spatstat.geom                crossdist FALSE
# crosspairs.ppp                  TRUE    spatstat.geom               crosspairs FALSE
# cut.ppp                         TRUE    spatstat.geom                      cut FALSE
# default.symbolmap.ppp           TRUE    spatstat.geom        default.symbolmap FALSE
# density.ppp                     TRUE spatstat.explore                  density FALSE
# densityAdaptiveKernel.ppp       TRUE spatstat.explore    densityAdaptiveKernel FALSE
# densityfun.ppp                  TRUE spatstat.explore               densityfun FALSE
# densityHeat.ppp                 TRUE spatstat.explore              densityHeat FALSE
# densityVoronoi.ppp              TRUE spatstat.explore           densityVoronoi FALSE
# dilation.ppp                    TRUE    spatstat.geom                 dilation FALSE
# distfun.ppp                     TRUE    spatstat.geom                  distfun FALSE
# distmap.ppp                     TRUE    spatstat.geom                  distmap FALSE
# domain.ppp                      TRUE    spatstat.geom                   domain FALSE
# duplicated.ppp                  TRUE    spatstat.geom               duplicated FALSE
# edit.ppp                        TRUE    spatstat.geom                     edit FALSE
# envelope.ppp                    TRUE spatstat.explore                 envelope FALSE
# erosion.ppp                     TRUE    spatstat.geom                  erosion FALSE
# fardist.ppp                     TRUE    spatstat.geom                  fardist FALSE
# flipxy.ppp                      TRUE    spatstat.geom                   flipxy FALSE
# Frame<-.ppp                     TRUE    spatstat.geom                  Frame<- FALSE
# has.close.ppp                   TRUE    spatstat.geom                has.close FALSE
# head.ppp                        TRUE    spatstat.geom                     head FALSE
# identify.ppp                    TRUE    spatstat.geom                 identify FALSE
# intensity.ppp                   TRUE    spatstat.geom                intensity FALSE
# is.connected.ppp                TRUE    spatstat.geom             is.connected FALSE
# is.empty.ppp                    TRUE    spatstat.geom                 is.empty FALSE
# is.marked.ppp                   TRUE    spatstat.geom                is.marked FALSE
# is.multitype.ppp                TRUE    spatstat.geom             is.multitype FALSE
# kppm.ppp                        TRUE   spatstat.model                     kppm FALSE
# lurking.ppp                     TRUE   spatstat.model                  lurking FALSE
# markformat.ppp                  TRUE    spatstat.geom               markformat FALSE
# marks.ppp                       TRUE    spatstat.geom                    marks FALSE
# marks<-.ppp                     TRUE    spatstat.geom                  marks<- FALSE
# multiplicity.ppp                TRUE    spatstat.geom             multiplicity FALSE
# nnclean.ppp                     TRUE spatstat.explore                  nnclean FALSE
# nncross.ppp                     TRUE    spatstat.geom                  nncross FALSE
# nndensity.ppp                   TRUE spatstat.explore                nndensity FALSE
# nndist.ppp                      TRUE    spatstat.geom                   nndist FALSE
# nnfun.ppp                       TRUE    spatstat.geom                    nnfun FALSE
# nnwhich.ppp                     TRUE    spatstat.geom                  nnwhich FALSE
# nobjects.ppp                    TRUE    spatstat.geom                 nobjects FALSE
# npoints.ppp                     TRUE    spatstat.geom                  npoints FALSE
# opening.ppp                     TRUE    spatstat.geom                  opening FALSE
# pairdist.ppp                    TRUE    spatstat.geom                 pairdist FALSE
# pcf.ppp                         TRUE spatstat.explore                      pcf FALSE
# periodify.ppp                   TRUE    spatstat.geom                periodify FALSE
# persp.ppp                       TRUE    spatstat.geom                    persp FALSE
# pixellate.ppp                   TRUE    spatstat.geom                pixellate FALSE
# plot.ppp                        TRUE    spatstat.geom                     plot FALSE
# ppm.ppp                         TRUE   spatstat.model                      ppm FALSE
# print.ppp                       TRUE    spatstat.geom                    print FALSE
# quadrat.test.ppp                TRUE spatstat.explore             quadrat.test FALSE
# quadratcount.ppp                TRUE    spatstat.geom             quadratcount FALSE
# quantess.ppp                    TRUE    spatstat.geom                 quantess FALSE
# rebound.ppp                     TRUE    spatstat.geom                  rebound FALSE
# relevel.ppp                     TRUE    spatstat.geom                  relevel FALSE
# relrisk.ppp                     TRUE spatstat.explore                  relrisk FALSE
# relriskHeat.ppp                 TRUE spatstat.explore              relriskHeat FALSE
# rescale.ppp                     TRUE    spatstat.geom                  rescale FALSE
# resolve.lambda.ppp              TRUE spatstat.explore           resolve.lambda FALSE
# resolve.lambdacross.ppp         TRUE spatstat.explore      resolve.lambdacross FALSE
# resolve.reciplambda.ppp         TRUE spatstat.explore      resolve.reciplambda FALSE
# rexplode.ppp                    TRUE    spatstat.geom                 rexplode FALSE
# rhohat.ppp                      TRUE spatstat.explore                   rhohat FALSE
# rjitter.ppp                     TRUE    spatstat.geom                  rjitter FALSE
# roc.ppp                         TRUE spatstat.explore                      roc FALSE
# rotate.ppp                      TRUE    spatstat.geom                   rotate FALSE
# round.ppp                       TRUE    spatstat.geom                    round FALSE
# rounding.ppp                    TRUE    spatstat.geom                 rounding FALSE
# rshift.ppp                      TRUE  spatstat.random                   rshift FALSE
# scalardilate.ppp                TRUE    spatstat.geom             scalardilate FALSE
# scanmeasure.ppp                 TRUE spatstat.explore              scanmeasure FALSE
# sdr.ppp                         TRUE spatstat.explore                      sdr FALSE
# segregation.test.ppp            TRUE spatstat.explore         segregation.test FALSE
# sharpen.ppp                     TRUE spatstat.explore                  sharpen FALSE
# shift.ppp                       TRUE    spatstat.geom                    shift FALSE
# Smooth.ppp                      TRUE spatstat.explore                   Smooth FALSE
# Smoothfun.ppp                   TRUE spatstat.explore                Smoothfun FALSE
# SmoothHeat.ppp                  TRUE spatstat.explore               SmoothHeat FALSE
# spatialCovariateEvidence.ppp    TRUE spatstat.explore spatialCovariateEvidence FALSE
# SpatialMedian.ppp               TRUE spatstat.explore            SpatialMedian FALSE
# SpatialQuantile.ppp             TRUE spatstat.explore          SpatialQuantile FALSE
# split.ppp                       TRUE    spatstat.geom                    split FALSE
# split<-.ppp                     TRUE    spatstat.geom                  split<- FALSE
# subset.ppp                      TRUE    spatstat.geom                   subset FALSE
# summary.ppp                     TRUE    spatstat.geom                  summary FALSE
# superimpose.ppp                 TRUE    spatstat.geom              superimpose FALSE
# tail.ppp                        TRUE    spatstat.geom                     tail FALSE
# text.ppp                        TRUE    spatstat.geom                     text FALSE
# unique.ppp                      TRUE    spatstat.geom                   unique FALSE
# uniquemap.ppp                   TRUE    spatstat.geom                uniquemap FALSE
# unitname.ppp                    TRUE    spatstat.geom                 unitname FALSE
# unitname<-.ppp                  TRUE    spatstat.geom               unitname<- FALSE
# unmark.ppp                      TRUE    spatstat.geom                   unmark FALSE
# unstack.ppp                     TRUE    spatstat.geom                  unstack FALSE
# Window.ppp                      TRUE    spatstat.geom                   Window FALSE
# Window<-.ppp                    TRUE    spatstat.geom                 Window<- FALSE

The examples in Chapter 35 require

library(groupedHyperframe)
search path & loadedNamespaces on author’s computer
search()
#  [1] ".GlobalEnv"                "package:groupedHyperframe" "package:stats"             "package:graphics"          "package:grDevices"         "package:utils"             "package:datasets"         
#  [8] "package:methods"           "Autoloads"                 "package:base"
loadedNamespaces() |> sort.int()
#  [1] "abind"             "base"              "cli"               "cluster"           "codetools"         "compiler"          "datasets"          "deldir"            "digest"           
# [10] "doParallel"        "dplyr"             "evaluate"          "farver"            "fastmap"           "fastmatrix"        "foreach"           "generics"          "geomtextpath"     
# [19] "GET"               "ggplot2"           "glue"              "goftest"           "graphics"          "grDevices"         "grid"              "gridExtra"         "groupedHyperframe"
# [28] "gtable"            "htmltools"         "htmlwidgets"       "iterators"         "jsonlite"          "knitr"             "lattice"           "lifecycle"         "magrittr"         
# [37] "Matrix"            "matrixStats"       "methods"           "nlme"              "otel"              "parallel"          "patchwork"         "pillar"            "pkgconfig"        
# [46] "polyclip"          "pracma"            "R6"                "RColorBrewer"      "rlang"             "rmarkdown"         "rstudioapi"        "S7"                "scales"           
# [55] "SpatialPack"       "spatstat.data"     "spatstat.explore"  "spatstat.geom"     "spatstat.random"   "spatstat.sparse"   "spatstat.univar"   "spatstat.utils"    "splines"          
# [64] "stats"             "survival"          "systemfonts"       "tensor"            "textshaping"       "tibble"            "tidyselect"        "tools"             "utils"            
# [73] "vctrs"             "viridisLite"       "xfun"              "yaml"

Table 35.1 summarizes the S3 methods for the class 'ppp' in package groupedHyperframe (v0.3.4),

Table 35.1: S3 methods groupedHyperframe::*.ppp (v0.3.4)
visible generic isS4
.rmax.ppp TRUE groupedHyperframe::.rmax FALSE
aggregate_marks.ppp TRUE groupedHyperframe::aggregate_marks FALSE
append_marks<-.ppp TRUE groupedHyperframe::`append_marks<-` FALSE
density_marks.ppp TRUE groupedHyperframe::density_marks FALSE
Emark_.ppp TRUE groupedHyperframe::Emark_ FALSE
Gcross_.ppp TRUE groupedHyperframe::Gcross_ FALSE
is.numeric.ppp TRUE base::is.numeric FALSE
Jcross_.ppp TRUE groupedHyperframe::Jcross_ FALSE
Kcross_.ppp TRUE groupedHyperframe::Kcross_ FALSE
kerndens.ppp TRUE groupedHyperframe::kerndens FALSE
Kmark_.ppp TRUE groupedHyperframe::Kmark_ FALSE
Lcross_.ppp TRUE groupedHyperframe::Lcross_ FALSE
markconnect_.ppp TRUE groupedHyperframe::markconnect_ FALSE
markcorr_.ppp TRUE groupedHyperframe::markcorr_ FALSE
markvario_.ppp TRUE groupedHyperframe::markvario_ FALSE
Math.ppp TRUE methods::Math FALSE
na.exclude.ppp TRUE stats::na.exclude FALSE
na.omit.ppp TRUE stats::na.omit FALSE
nncross_.ppp TRUE groupedHyperframe::nncross_ FALSE
pairwise_cor_spatial.ppp TRUE groupedHyperframe::pairwise_cor_spatial FALSE
quantile.ppp TRUE stats::quantile FALSE
rlabelRes.ppp TRUE groupedHyperframe::rlabelRes FALSE
Summary.ppp TRUE methods::Summary FALSE
Vmark_.ppp TRUE groupedHyperframe::Vmark_ FALSE

35.1 Missing Marks Handling

The S3 methods na.omit.ppp() and na.exclude.ppp() omits and excludes, respectively, the missing marks from a point-pattern. Both functions return a point-pattern.

If missingness exists in the marks, the 'na.action'-attribute of the marks is saved as an attribute of the returned point-pattern.

Listing 35.3: Exception: functions na.omit.ppp() and na.exclude.ppp() on 'none' mark-format
spatstat.data::vesicles |>
  na.omit() |>
  identical(y = spatstat.data::vesicles) |>
  stopifnot()
spatstat.data::vesicles |>
  na.exclude()|>
  identical(y = spatstat.data::vesicles) |>
  stopifnot()
Listing 35.4: Exception: functions na.omit.ppp() and na.exclude.ppp() on 'vector' mark-format, no missingness
spatstat.data::ants |>
  na.omit() |>
  identical(y = spatstat.data::ants) |>
  stopifnot()
spatstat.data::ants |>
  na.exclude() |>
  identical(y = spatstat.data::ants) |>
  stopifnot()
Listing 35.5: Example: functions na.omit.ppp() and na.exclude.ppp() on 'dataframe' mark-format
nbfires_omit = spatstat.data::nbfires |> 
  na.omit() 
nbfires_exclude = spatstat.data::nbfires |> 
  na.exclude()
list(
  nbfires = spatstat.data::nbfires,
  omit = nbfires_omit, 
  exclude = nbfires_exclude
) |> 
  vapply(FUN = spatstat.geom::npoints.ppp, FUN.VALUE = NA_integer_)
# nbfires    omit exclude 
#    7108    6989    6989
list(
  omit = nbfires_omit,
  exclude = nbfires_exclude
) |> 
  vapply(FUN = \(i) {
    i |>
      attr(which = 'na.action', exact = TRUE) |> 
      attr(which = 'class', exact = TRUE)
  }, FUN.VALUE = NA_character_)
#      omit   exclude 
#    "omit" "exclude"

Note that the function spatstat.geom::ppp() (v3.7.0.6) already removes missing \(x\)- and \(y\)-coords in the creation of a point-pattern.

Note that the S3 method spatstat.geom::plot.ppp() (v3.7.0.6) also removes missing marks (email with Dr. Baddeley, 2025-01-07).

35.2 Are Marks Numeric?

The S3 method is.numeric.ppp() determines whether each of the marks, if any, in a point-pattern are numeric.

Listing 35.6: Exception: function is.numeric.ppp() on 'none' mark-format
spatstat.data::vesicles |>
  is.numeric()
# logical(0)
Listing 35.7: Example: function is.numeric.ppp() on numeric mark
spatstat.data::longleaf |>
  is.numeric()
# [1] TRUE
Listing 35.8: Example: function is.numeric.ppp() on multi-type mark
spatstat.data::ants |>
  is.numeric()
# [1] FALSE

The S3 methods is.numeric.ppp() and spatstat.geom::is.multitype.ppp() (v3.7.0.6) behave differently for a point-pattern with 'dataframe' mark-format, e.g., betacells (Section 9.4).

Listing 35.9: Review: function is.multitype.ppp() on 'dataframe' mark-format
spatstat.data::betacells |>
  spatstat.geom::is.multitype.ppp()
# [1] FALSE
Listing 35.10: Example: functions is.numeric.ppp() on 'dataframe' mark-format
spatstat.data::betacells |>
  is.numeric()
#  type  area 
# FALSE  TRUE

35.3 Group-Generic of Numeric Mark(s)

35.3.1 Math

Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.2) of the Math-groupGeneric,

Table 35.2: S3 methods of methods::Math (v4.5.2)
visible isS4
Math.fvlist TRUE FALSE
Math.ppp TRUE FALSE
Math.ppplist TRUE FALSE
Math.psp TRUE FALSE
Math.tess TRUE FALSE

The S3 method Math.ppp() transforms one or more numeric marks of a point-pattern, and returns a point-pattern with the transformed marks. The \(x\)- and \(y\)-coordinates and the multi-type marks of the input point-pattern remain unchanged. This function, as well as the S3 method Math.tess() (Section 41.1.1), serves a similar purpose (Table 35.3) to the S3 methods spatstat.explore::Math.fv() (v3.7.0.4) and spatstat.geom::Math.im() (v3.7.0.6).

Table 35.3: Methods in Math Group-Generic
Math.ppp() Math.tess() Math.fv() Math.im()
Input & Output ppp.object (Chapter 35) tessellation (Chapter 41) fv.object (Chapter 19) im.object (Chapter 27)
Operates On numeric mark(s) numeric mark(s) function-values (Listing 19.6) “grey value” at each pixel
Does Not Alter multi-type marks (if any), \(x\)- and \(y\)-coordinates, observation window, etc. observation window, tiles, etc. function argument (Listing 19.6), etc. \(x\)- and \(y\)-coordinates, dimension, etc.

Listing 35.11 applies the log-transformations on the point-pattern bronzefilter (Section 9.5) with 'vector' mark-format.

Listing 35.11: Example: log-transformations on 'vector' mark-format
list(
  original = spatstat.data::bronzefilter,
  log = spatstat.data::bronzefilter |> log(),
  log1p = spatstat.data::bronzefilter |> log1p()
) |>
  lapply(FUN = spatstat.geom::summary.ppp) |>
  lapply(FUN = getElement, name = 'marks')
# $original
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   0.013   0.120   0.160   0.167   0.200   0.467 
# 
# $log
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
# -4.3428 -2.1203 -1.8326 -1.8989 -1.6094 -0.7614 
# 
# $log1p
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
# 0.01292 0.11333 0.14842 0.15244 0.18232 0.38322

Listing 35.12 applies the log-transformation on the numeric marks in the point-pattern betacells (Section 9.4) with 'dataframe' mark-format.

Listing 35.12: Example: log-transformations on numeric marks in 'dataframe' mark-format
list(
  original = spatstat.data::betacells,
  log = spatstat.data::betacells |> log()
) |>
  lapply(FUN = spatstat.geom::summary.ppp) |>
  lapply(FUN = getElement, name = 'marks')
# $original
#   type         area      
#  off:70   Min.   :168.3  
#  on :65   1st Qu.:248.8  
#           Median :279.4  
#           Mean   :291.2  
#           3rd Qu.:324.2  
#           Max.   :514.4  
# 
# $log
#   type         area      
#  off:70   Min.   :5.126  
#  on :65   1st Qu.:5.517  
#           Median :5.633  
#           Mean   :5.653  
#           3rd Qu.:5.782  
#           Max.   :6.243

Listing 35.13 showcases the exception handling of the log-transformations on the \(x\)- and \(y\)-coordinates-only point-pattern vesicles (Section 9.24).

Listing 35.13: Exception: log-transformations on 'none' mark-format
list(
  spatstat.data::vesicles |> log(),
  spatstat.data::vesicles |> log1p(),
  spatstat.data::vesicles |> log2(),
  spatstat.data::vesicles |> log10()
) |> 
  vapply(FUN = identical, y = spatstat.data::vesicles, FUN.VALUE = NA) |>
  stopifnot()

35.3.2 Summary

Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.4) of the Summary-groupGeneric,

Table 35.4: S3 methods of methods::Summary (v4.5.2)
visible isS4
Summary.fvlist TRUE FALSE
Summary.ppp TRUE FALSE
Summary.ppplist TRUE FALSE
Summary.psp TRUE FALSE
Summary.tess TRUE FALSE

The S3 method Summary.ppp() summarizes one or more numeric marks of a point-pattern. This function, as well as the S3 method Summary.tess() (Section 41.1.2), serves a similar purpose (Table 35.5) to the S3 methods spatstat.explore::Summary.fv() (v3.7.0.4) and spatstat.geom::Summary.im() (v3.7.0.6).

Table 35.5: Methods in Summary Group-Generic
Summary.ppp() Summary.tess() Summary.fv() Summary.im()
Input ppp.object (Chapter 35) tessellation (Chapter 41) fv.object (Chapter 19) im.object (Chapter 27)
Operates On each numeric mark(s) each numeric mark(s) all function-values (Listing 19.12) “grey value” at each pixel

Listing 35.14 and Listing 35.15 find the minimum and the range of the numeric mark in the point-pattern bronzefilter (Section 9.5) with 'vector' mark-format.

Listing 35.14: Example: minimum of numeric marks on 'vector' mark-format
spatstat.data::bronzefilter |>
  min()
# [1] 0.013
Listing 35.15: Example: range of numeric marks on 'vector' mark-format
spatstat.data::bronzefilter |>
  range()
# [1] 0.013 0.467

Listing 35.16 - Listing 35.19 find the minimum and the range of the numeric mark(s) in the point-patterns betacells (Section 9.4) and finpines (Section 9.11) with 'dataframe' mark-format.

Listing 35.16: Example: minimum of one numeric mark in 'dataframe' mark-format
spatstat.data::betacells |>
  min()
#  area 
# 168.3
Listing 35.17: Example: range of one numeric mark in 'dataframe' mark-format
spatstat.data::betacells |>
  range()
# $area
# [1] 168.3 514.4
Listing 35.18: Example: minimum of multiple numeric marks in 'dataframe' mark-format
spatstat.data::finpines |>
  min()
# diameter   height 
#      0.0      0.8
Listing 35.19: Example: range of multiple numeric marks in 'dataframe' mark-format
spatstat.data::finpines |>
  range()
# $diameter
# [1] 0 7
# 
# $height
# [1] 0.8 5.4

Listing 35.20 showcases the exception handling with an \(x\)- and \(y\)-coordinates-only point-pattern vesicles (Section 9.24).

Listing 35.20: Exception: minimum and range of numeric mark on 'none' mark-format
spatstat.data::vesicles |>
  min() |>
  is.null() |> stopifnot()
spatstat.data::vesicles |>
  range() |>
  is.null() |> stopifnot()

35.4 Kernel Density (Estimates) of Numeric Mark(s)

The S3 generic function density_marks() finds the kernel densities (Becker, Chambers, and Wilks 1988) of the numeric mark(s). Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.6),

Table 35.6: S3 methods of groupedHyperframe::density_marks (v0.3.4)
visible isS4
density_marks.ppp TRUE FALSE
density_marks.ppplist TRUE FALSE

The S3 method density_marks.ppp() finds the kernel densities of one or more numeric marks in a point-pattern. Table 35.7 shows the difference between the S3 methods density_marks.ppp() and spatstat.explore::density.ppp() (v3.7.0.4),

Table 35.7: Functions density_marks.ppp() versus density.ppp()
density.ppp() density_marks.ppp()
Computes fixed-bandwidth kernel estimate (Diggle 1985) of the intensity function from a point-pattern, i.e., the \(x\)- and \(y\)-coords only (Listing 35.31) kernel density (Becker, Chambers, and Wilks 1988) of the numeric mark(s)
Returns an im.object (Chapter 27) a (list of) stats::density object(s)

The S3 method kerndens.ppp() (Section 32.1, Table 32.2) finds the kernel density estimates of one or more numeric marks of a point-pattern; this is simply a wrapper of the S3 method density_marks.ppp().

Listing 35.21 and Listing 35.22 showcase the exception handling for the \(x\)- and \(y\)-coordinates-only point-pattern vesicles (Section 9.24).

Listing 35.21: Exception: function density_marks.ppp() on 'none' mark-format
spatstat.data::vesicles |>
  density_marks() |>
  is.null() |> stopifnot()
Listing 35.22: Exception: function kerndens.ppp() on 'none' mark-format
spatstat.data::vesicles |>
  kerndens() |>
  is.null() |> stopifnot()

Listing 35.23 and Listing 35.24 showcase the exception handling for the point-pattern ants (Section 9.2) with one multi-type mark.

Listing 35.23: Exception: function density_marks.ppp() on multi-type mark in 'vector' mark-format
spatstat.data::ants |>
  density_marks() |>
  is.null() |> stopifnot()
Listing 35.24: Exception: function kerndens.ppp() on multi-type mark in 'vector' mark-format
spatstat.data::ants |>
  kerndens() |>
  is.null() |> stopifnot()

Listing 35.25 and Listing 35.26 find the kernel density (estimates) of the numeric mark in the point-pattern longleaf (Section 9.17).

Listing 35.25: Example: function density_marks.ppp() on numeric mark in 'vector' mark-format
spatstat.data::longleaf |>
  density_marks()
# 
# Call:
#   density.default(x = m)
# 
# Data: m (584 obs.);   Bandwidth 'bw' = 4.615
# 
#        x                y            
#  Min.   :-11.84   Min.   :1.759e-06  
#  1st Qu.: 13.55   1st Qu.:1.665e-03  
#  Median : 38.95   Median :1.227e-02  
#  Mean   : 38.95   Mean   :9.823e-03  
#  3rd Qu.: 64.35   3rd Qu.:1.624e-02  
#  Max.   : 89.74   Max.   :2.320e-02
Listing 35.26: Example: function kerndens.ppp() on numeric mark in 'vector' mark-format
spatstat.data::longleaf |>
  kerndens(n = 8L)
# [1] 8.403103e-05 2.019181e-02 1.471192e-02 1.438080e-02 1.612033e-02 4.244355e-03 6.127754e-04 1.759222e-06

Listing 35.27 and Listing 35.28 find the kernel density (estimates) of the numeric mark area in the point-pattern betacells (Section 9.4).

Listing 35.27: Example: function density_marks.ppp() on numeric mark(s) in 'dataframe' mark-format
spatstat.data::betacells |>
  density_marks()
# $area
# 
# Call:
#   density.default(x = `$area`)
# 
# Data: $area (135 obs.);   Bandwidth 'bw' = 18.99
# 
#        x               y            
#  Min.   :111.3   Min.   :1.736e-06  
#  1st Qu.:226.3   1st Qu.:1.385e-04  
#  Median :341.4   Median :9.455e-04  
#  Mean   :341.4   Mean   :2.170e-03  
#  3rd Qu.:456.4   3rd Qu.:4.087e-03  
#  Max.   :571.4   Max.   :7.065e-03
Listing 35.28: Example: function kerndens.ppp() on numeric mark(s) in 'dataframe' mark-format
spatstat.data::betacells |>
  kerndens(n = 8L)
# $area
# [1] 2.530826e-06 9.483771e-04 6.254928e-03 5.117580e-03 2.486671e-03 6.781429e-04 1.411284e-04 1.736171e-06

Listing 35.29 and Listing 35.30 find the kernel density (estimates) of the two numeric marks diameter and height in the point-pattern finpines (Section 9.11).

Listing 35.29: Example: function density_marks.ppp() on two numeric marks in 'dataframe' mark-format
spatstat.data::finpines |>
  density_marks()
# $diameter
# 
# Call:
#   density.default(x = `$diameter`)
# 
# Data: $diameter (126 obs.);   Bandwidth 'bw' = 0.5106
# 
#        x                 y            
#  Min.   :-1.5318   Min.   :0.0003457  
#  1st Qu.: 0.9841   1st Qu.:0.0352813  
#  Median : 3.5000   Median :0.0574541  
#  Mean   : 3.5000   Mean   :0.0991600  
#  3rd Qu.: 6.0159   3rd Qu.:0.1973683  
#  Max.   : 8.5318   Max.   :0.2662931  
# 
# $height
# 
# Call:
#   density.default(x = `$height`)
# 
# Data: $height (126 obs.); Bandwidth 'bw' = 0.3912
# 
#        x                 y            
#  Min.   :-0.3736   Min.   :0.0001153  
#  1st Qu.: 1.3632   1st Qu.:0.0228185  
#  Median : 3.1000   Median :0.1429140  
#  Mean   : 3.1000   Mean   :0.1436587  
#  3rd Qu.: 4.8368   3rd Qu.:0.2651729  
#  Max.   : 6.5736   Max.   :0.2887832
Listing 35.30: Example: function kerndens.ppp() on two numeric marks in 'dataframe' mark-format
spatstat.data::finpines |>
  kerndens(n = 8L)
# $diameter
# [1] 0.0005538254 0.0725488203 0.2527530420 0.2070950918 0.0839416301 0.0522232298 0.0348548329 0.0003456594
# 
# $height
# [1] 0.0001987181 0.0487205156 0.2799629521 0.2648249560 0.2431292593 0.1364985536 0.0271086981 0.0001152871

Listing 35.31 shows that the S3 method spatstat.explore::density.ppp() (v3.7.0.4) only uses the \(x\)-and-\(y\) coordinates of a point-pattern.

Listing 35.31: Review: function spatstat.explore::density.ppp() (Baddeley, Rubak, and Turner 2015)
a1 = spatstat.data::betacells |> 
  spatstat.explore::density.ppp()
a0 = spatstat.data::betacells |>
  spatstat.geom::unmark.ppp() |>
  spatstat.explore::density.ppp()
stopifnot(identical(a0, a1))

35.5 Quantile of Numeric Mark(s)

Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.8) of the generic function stats::quantile(),

Table 35.8: S3 methods of stats::quantile (v4.5.2)
visible isS4
quantile.anylist TRUE FALSE
quantile.hyperframe TRUE FALSE
quantile.ppp TRUE FALSE
quantile.ppplist TRUE FALSE

The S3 method quantile.ppp() finds the quantiles of one or more numeric marks in a point-pattern. This is completely different from the S3 method spatstat.explore::SpatialQuantile.ppp() (v3.7.0.4).

Listing 35.32 showcases the exception handling for the \(x\)- and \(y\)-coordinates-only point-pattern vesicles (Section 9.24).

Listing 35.32: Exception: function quantile.ppp() on 'none' mark-format
spatstat.data::vesicles |>
  quantile() |>
  is.null() |> stopifnot()

Listing 35.33 showcases the exception handling for the point-pattern ants (Section 9.2) with one multi-type mark.

Listing 35.33: Exception: function quantile.ppp() on multi-type mark in 'vector' mark-format
spatstat.data::ants |>
  quantile() |>
  is.null() |> stopifnot()

Listing 35.34 finds the quantiles of the numeric mark in the point-pattern longleaf (Section 9.17).

Listing 35.34: Example: function quantile.ppp() on numeric mark in 'vector' mark-format
spatstat.data::longleaf |>
  quantile()
#     0%    25%    50%    75%   100% 
#  2.000  9.100 26.150 42.125 75.900

Listing 35.35 finds the quantiles of the numeric mark area in the point-pattern betacells (Section 9.4).

Listing 35.35: Example: function quantile.ppp() on numeric mark(s) in 'dataframe' mark-format
spatstat.data::betacells |>
  quantile()
# $area
#     0%    25%    50%    75%   100% 
# 168.30 248.85 279.40 324.25 514.40

Listing 35.36 finds the quantiles of the two numeric marks diameter and height in the point-pattern finpines (Section 9.11).

Listing 35.36: Example: function quantile.ppp() on two numeric marks in 'dataframe' mark-format
spatstat.data::finpines |>
  quantile()
# $diameter
#   0%  25%  50%  75% 100% 
#    0    1    2    3    7 
# 
# $height
#    0%   25%   50%   75%  100% 
# 0.800 1.825 2.850 3.600 5.400

35.6 Nearest Neighbour Distance of Multi-Type Marks, Alternative Interface

Function .nncross() is a wrapper of the function spatstat.geom::nncross(., what = 'dist') (v3.7.0.6, Listing 35.39) to provide a user-interface (Listing 35.37) consistent with the function spatstat.explore::Gcross() (v3.7.0.4, Listing 35.38), etc., which allows the internal batch-processing mechanism (Section 35.14) to be shared between Table 35.24 and Table 35.25.

Listing 35.37: Example: user-interface of .nncross()
.nncross
# function (X, i, j, ...) 
# ✂️ --- output truncated --- ✂️
Listing 35.38: Review: user-interface of spatstat.explore::Gcross()
spatstat.explore::Gcross
# function (X, i, j, r = NULL, breaks = NULL, ..., rmax = NULL, 
#     correction = c("rs", "km", "han")) 
# ✂️ --- output truncated --- ✂️
Listing 35.39: Review: user-interface of spatstat.geom::nncross()
spatstat.geom::nncross
# function (X, Y, ...) 
# ✂️ --- output truncated --- ✂️

Listing 35.40 computes the distance to the nearest neighbour of points with 'Messor'-mark from each point with 'Cataglyphis'-mark in the point-pattern ants (Section 9.2) by using the functions spatstat.geom::split.ppp() and spatstat.geom::nncross.ppp().

Listing 35.40: Review: function spatstat.geom::nncross.ppp()
nn = spatstat.data::ants |>
  spatstat.geom::split.ppp() |>
  with.default(expr = {
    spatstat.geom::nncross.ppp(X = Cataglyphis, Y = Messor, what = 'dist')
  })

Listing 35.41 creates an identical return as Listing 35.40 using the function .nncross() with integer indices corresponding to the levels of the multi-type marks in ants (Section 9.2), i.e, 1L for 'Cataglyphis' and 2L for 'Messor'.

Listing 35.41: Example: function .nncross() with integer levels indices
spatstat.data::ants |> 
  .nncross(i = 1L, j = 2L) |>
  identical(y = nn) |> 
  stopifnot()

Listing 35.42 creates an identical return as Listing 35.40 using the function .nncross() with character levels of the multi-type marks in the point-pattern ants (Section 9.2).

Listing 35.42: Example: function .nncross() with character levels
spatstat.data::ants |> 
  .nncross(i = 'Cataglyphis', j = 'Messor') |>
  identical(y = nn) |> 
  stopifnot()

Listing 35.43 showcases the exception handling when the character values supplied to the i and j parameters do not match any levels of the multi-type marks in the point-pattern ants (Section 9.2).

Listing 35.43: Exception: function .nncross(), non-existing levels
spatstat.data::ants |>
  .nncross(i = 'a', j = 'b') |>
  is.null() |> stopifnot()

35.7 Aggregate Marks-Statistics

The S3 generic function aggregate_marks() aggregates various statistics (other than the quantiles, Section 35.5) of the marks within a point-pattern, or within each point-pattern of an object containing one or more point-patterns. Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.9),

Table 35.9: S3 methods of groupedHyperframe::aggregate_marks (v0.3.4)
visible isS4
aggregate_marks.hyperframe TRUE FALSE
aggregate_marks.ppp TRUE FALSE
aggregate_marks.ppplist TRUE FALSE

The S3 method aggregate_marks.ppp() aggregates a set of fully customizable summary statistics, in the parameter FUN or expr, of the marks within a point-pattern. For each type of the mark-format of the input point-pattern,

  • markformat = 'none' (Section 35.7.1): returns an invisible NULL-value.
  • markformat = 'vector' (Section 35.7.2): computes the summary statistics of the numeric- or multi-type marks.
  • markformat = 'dataframe' (Section 35.7.3): aggregates the numeric- and/or multi-type marks, according to a grouping structure determined by one-or-more multi-type-marks in the parameter by (Section 35.7.3.1), using the workhorse function stats::aggregate.data.frame().

The returned aggregated summary statistics can be vectorized for downstream use (Section 36.4).

Table 35.10 explains how the S3 method aggregate_marks.ppp() generalizes the aggregation-of-marks, compared to the S3 method spatstat.geom::summary.ppp() (v3.7.0.6).

Table 35.10: Functions aggregate_marks.ppp() versus summary.ppp()
aggregate_marks.ppp() summary.ppp()
Summary of \(x\)- and \(y\)-Coordinates No Yes
Summary of Observation Window No Yes
Mark(s) Statistics Fully customizable in parameters FUN or expr Only those available in function base::summary.default()
By Group(s) Yes (Section 35.7.3.1) No (Listing 35.56)
Returns a list or vector a summary.ppp object (Listing 35.44)

Listing 35.44 summarizes the S3 methods for the class 'summary.ppp' in the spatstat.* family of packages.

Listing 35.44: S3 methods spatstat.*::*.summary.ppp
Code
suppressPackageStartupMessages(library(spatstat))
.S3methods(class = 'summary.ppp', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = grepl(pattern = '^spatstat\\.', x = from))
#                   visible          from generic  isS4
# print.summary.ppp    TRUE spatstat.geom   print FALSE

35.7.1 'none' mark-format

Listing 35.45 showcases the exception handling with the point-pattern vesicles (Section 9.24) without any mark.

Listing 35.45: Exception: function aggregate_marks.ppp() on 'none' mark-format
spatstat.data::vesicles |> 
  aggregate_marks() |>
  is.null() |> stopifnot()

Listing 35.46 shows the S3 method spatstat.geom::summary.ppp() on a point-pattern without any mark.

Listing 35.46: Review: function summary.ppp() on 'none' mark-format
spatstat.data::vesicles |>
  spatstat.geom::summary.ppp() |>
  getElement(name = 'marks') |>
  is.null() |> stopifnot()

35.7.2 'vector' mark-format

Listing 35.47, Listing 35.48 and Listing 35.49 aggregate the sample mean, or both the sample mean and the sample standard deviation, or the common summary statistics, of the numeric mark in the point-pattern spruces (Section 9.21). The parameter z in Listing 35.48 represents the numeric mark as a vector, and may be replaced by any other symbol of the user’s choice.

Listing 35.47: Example: sample mean
spatstat.data::spruces |> 
  aggregate_marks(FUN = mean)
#      mean 
# 0.2503731
Listing 35.48: Example: sample mean and sd
spatstat.data::spruces |> 
  aggregate_marks(FUN = \(z) c(mean = mean(z), sd = sd(z)))
#       mean         sd 
# 0.25037313 0.04697474
Listing 35.49: Example: common summary statistics
spatstat.data::spruces |> 
  aggregate_marks(FUN = summary.default)
#      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
# 0.1600000 0.2200000 0.2450000 0.2503731 0.2700000 0.3700000

Listing 35.50 provides equivalent return as Listing 35.49 using the S3 method spatstat.geom::summary.ppp().

Listing 35.50: Review: function summary.ppp(), numeric mark in 'vector' mark-format
spatstat.data::spruces |> 
  spatstat.geom::summary.ppp() |>
  getElement(name = 'marks')
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#  0.1600  0.2200  0.2450  0.2504  0.2700  0.3700

Listing 35.51 and Listing 35.52 aggregate the (relative) frequencies of the multi-type mark in the point-pattern ants (Section 9.2). The parameter z in Listing 35.52 represents the multi-type mark as a vector, and may be replaced by any other symbol of the user’s choice.

Listing 35.51: Example: frequencies
spatstat.data::ants |> 
  aggregate_marks(FUN = table)
# Cataglyphis      Messor 
#          29          68
Listing 35.52: Example: relative frequencies
spatstat.data::ants |> 
  aggregate_marks(FUN = \(z) table(z)/length(z))
# Cataglyphis      Messor 
#   0.2989691   0.7010309

Listing 35.53 provides equivalent return as Listing 35.51 and Listing 35.52 using the S3 method spatstat.geom::summary.ppp().

Listing 35.53: Review: function summary.ppp(), multi-type mark in 'vector' mark-format
spatstat.data::ants |> 
  spatstat.geom::summary.ppp() |>
  getElement(name = 'marks')
#             frequency proportion    intensity
# Cataglyphis        29  0.2989691 6.761144e-05
# Messor             68  0.7010309 1.585372e-04

35.7.3 'dataframe' mark-format

Listing 35.54 aggregates the numeric mark area and multi-type mark type in the point-pattern betacells (Section 9.4) using the statistics specified as R language in the parameter expr.

Listing 35.54: Example: numeric- and multi-type mark in 'dataframe' mark-format
spatstat.data::betacells |>
  aggregate_marks(expr = list(
    type = table(type),
    area = summary.default(area)
  ))
# $type
# type
# off  on 
#  70  65 
# 
# $area
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   168.3   248.8   279.4   291.2   324.2   514.4

Listing 35.55 vectorizes the return of Listing 35.54.

Listing 35.55: Example: numeric- and multi-type mark in 'dataframe' mark-format, vectorized
spatstat.data::betacells |>
  aggregate_marks(expr = list(
    type = table(type),
    area = summary.default(area)
  ), vectorize = TRUE)
#     type.off      type.on    area.Min. area.1st Qu.  area.Median    area.Mean area.3rd Qu.    area.Max. 
#      70.0000      65.0000     168.3000     248.8500     279.4000     291.2081     324.2500     514.4000

Listing 35.56 provides equivalent return as Listing 35.54 and Listing 35.55 using the S3 method spatstat.geom::summary.ppp().

Listing 35.56: Review: function summary.ppp(), numeric and multi-type mark in 'dataframe' mark-format
spatstat.data::betacells |>
  spatstat.geom::summary.ppp() |>
  getElement(name = 'marks')
#   type         area      
#  off:70   Min.   :168.3  
#  on :65   1st Qu.:248.8  
#           Median :279.4  
#           Mean   :291.2  
#           3rd Qu.:324.2  
#           Max.   :514.4

35.7.3.1 Use of Parameter by

The S3 method aggregate_marks.ppp() accepts a two-sided formula for the parameter by, if the input point-pattern has 'dataframe' mark-format. The left-hand-side of the formula by contains the name(s) of one or more mark(s) to be summarized, e.g.,

The right-hand-side of the formula by contains the name(s) of one or more multi-type mark(s) to indicate the grouping structure of the aggregation, e.g.,

Note that the S3 method spatstat.geom::summary.ppp() (v3.7.0.6) does not provide summary statistics by-group (Listing 35.56).

35.7.3.1.1 Aggregate by One Group

Listing 35.57 and Listing 35.58 aggregate the numeric mark area by the multi-type mark type of the point-pattern betacells (Section 9.4), using the sample mean, or both the sample mean and the sample standard deviation. The parameter z in Listing 35.58 represents the numeric mark area in the left-hand-side of the formula by, and may be replaced by any other symbol of the user’s choice.

Listing 35.57: Example: sample mean of area-by-type
spatstat.data::betacells |>
  aggregate_marks(by = area ~ type, FUN = mean)
#   type     area
# 1  off 259.7214
# 2   on 325.1169
Listing 35.58: Example: sample mean and sd of area-by-type
spatstat.data::betacells |>
  aggregate_marks(by = area ~ type, FUN = \(z) {
    c(mean = mean(z), sd = sd(z))
  })
#   type area.mean   area.sd
# 1  off 259.72143  40.86083
# 2   on 325.11692  60.71534

Listing 35.59 and Listing 35.60 vectorize the returns of Listing 35.57 and Listing 35.58.

Listing 35.59: Example: sample mean of area-by-type, vectorized
spatstat.data::betacells |>
  aggregate_marks(by = area ~ type, FUN = mean, vectorize = TRUE)
# off.area  on.area 
# 259.7214 325.1169
Listing 35.60: Example: sample mean and sd of area-by-type, vectorized
spatstat.data::betacells |>
  aggregate_marks(by = area ~ type, FUN = \(z) {
    c(mean = mean(z), sd = sd(z))
  }, vectorize = TRUE)
# off.area.mean   off.area.sd  on.area.mean    on.area.sd 
#     259.72143      40.86083     325.11692      60.71534

Listing 35.61 and Listing 35.62 aggregate one multi-type mark season by another multi-type mark group of the point-pattern gorillas (Section 9.13), using the (relative) frequencies. The parameter z in Listing 35.62 represents the multi-type mark season in the left-hand-side of the formula by, and may be replaced by any other symbol of the user’s choice.

Listing 35.61: Example: frequencies of season-by-group
spatstat.data::gorillas |>
  aggregate_marks(by = season ~ group, FUN = table)
#   group season.dry season.rainy
# 1 major        150          200
# 2 minor        125          172
Listing 35.62: Example: relative frequencies of season-by-group
spatstat.data::gorillas |>
  aggregate_marks(by = season ~ group, FUN = \(z) table(z)/length(z))
#   group season.dry season.rainy
# 1 major  0.4285714    0.5714286
# 2 minor  0.4208754    0.5791246

Listing 35.63 and Listing 35.64 vectorize the returns of Listing 35.61 and Listing 35.62.

Listing 35.63: Example: frequencies of season-by-group, vectorized
spatstat.data::gorillas |>
  aggregate_marks(by = season ~ group, FUN = table, vectorize = TRUE)
#   major.season.dry major.season.rainy   minor.season.dry minor.season.rainy 
#                150                200                125                172
Listing 35.64: Example: relative frequencies of season-by-group, vectorized
spatstat.data::gorillas |>
  aggregate_marks(by = season ~ group, FUN = \(z) {
    table(z)/length(z)
  }, vectorize = TRUE)
#   major.season.dry major.season.rainy   minor.season.dry minor.season.rainy 
#          0.4285714          0.5714286          0.4208754          0.5791246
35.7.3.1.2 Aggregate One-or-More Marks by Interaction of Multiple Groups

Listing 35.65 creates a point-pattern nbfL from the point-pattern nbfires (Section 9.19) by

  1. appending a numeric mark hr.last (Section 35.9), the time difference in hours between the put-out out.date and the discovery dis.date, to the existing marks;
  2. selecting a subset of points that represent 'forest' and/or 'grass' fires caused by railroads 'rrds' and/or recreation 'rec';
  3. removing the points with any missing marks (Section 35.1);
  4. performing log1p-transformations on the numeric marks (Section 35.3.1) fnl.size and hr.last.
Listing 35.65: Data: a point-pattern nbfL
nbfL. = spatstat.data::nbfires
append_marks(nbfL.) = nbfL. |>
  spatstat.geom::marks.ppp() |>
  with.default(expr = {
    tmp = out.date - dis.date
    units(tmp) = 'hours'
    list(hr.last = as.numeric(tmp))
  })
nbfL = nbfL. |>
  spatstat.geom::subset.ppp(
    subset = (fire.type %in% c('forest', 'grass')) & (cause %in% c('rrds', 'rec')), 
    select = c('fire.type', 'cause', 'fnl.size', 'hr.last')
  ) |>
  na.omit() |>
  log1p()
rm(nbfL.)

Listing 35.66 aggregates the log1p-transformed numeric mark fnl.size by the interaction of two multi-type marks fire.type and cause in the point-pattern nbfL (Listing 35.65), using the sample mean and the sample standard deviation sd. The parameter z in Listing 35.66 represents the log1p-transformed numeric mark fnl.size in the left-hand-side of the formula by, and may be replaced by any other symbol of the user’s choice.

Listing 35.66: Example: sample mean and sd of log1p-transformed fnl.size-by-fire.type:cause (Listing 35.65)
nbfL |>
  aggregate_marks(by = fnl.size ~ fire.type:cause, FUN = \(z) {
    c(mean = mean(z), sd = sd(z))
  })
#   fire.type cause fnl.size.mean fnl.size.sd
# 1    forest  rrds     0.8647287   0.9269129
# 2     grass  rrds     0.3416982   0.4392035
# 3    forest   rec     0.4799249   0.7390220
# 4     grass   rec     0.3740750   0.5717532

Listing 35.67 aggregates the log1p-transformed numeric marks fnl.size and hr.last by the interaction of two multi-type marks fire.type and cause in the point-pattern nbfL (Listing 35.65), using the sample mean and the sample standard deviation sd. The parameter z in Listing 35.67 represents the log1p-transformed numeric marks fnl.size and hr.last, respectively, in the left-hand-side of the formula by, and may be replaced by any other symbol of the user’s choice. Note that the use of cbind() in the formula by follows that of the S3 method stats::aggregate.data.frame().

Listing 35.67: Example: sample mean and sd of log1p-transformed fnl.size-and-hr.last-by-fire.type:cause (Listing 35.65)
nbfL |>
  aggregate_marks(by = cbind(fnl.size, hr.last) ~ fire.type:cause, FUN = \(z) {
    c(mean = mean(z), sd = sd(z))
  })
#   fire.type cause fnl.size.mean fnl.size.sd hr.last.mean hr.last.sd
# 1    forest  rrds     0.8647287   0.9269129    3.2775133  1.0379506
# 2     grass  rrds     0.3416982   0.4392035    2.1677729  1.1694497
# 3    forest   rec     0.4799249   0.7390220    2.7868615  1.3290827
# 4     grass   rec     0.3740750   0.5717532    1.3526997  0.9957785

Listing 35.68 and Listing 35.69 vectorize the returns of Listing 35.66 and Listing 35.67.

Listing 35.68: Example: sample mean and sd of log1p-transformed fnl.size-by-fire.type:cause, vectorized (Listing 35.65)
nbfL |>
  aggregate_marks(by = fnl.size ~ fire.type:cause, FUN = \(z) {
    c(mean = mean(z), sd = sd(z))
  }, vectorize = TRUE)
# forest.rrds.fnl.size.mean   forest.rrds.fnl.size.sd  grass.rrds.fnl.size.mean    grass.rrds.fnl.size.sd  forest.rec.fnl.size.mean    forest.rec.fnl.size.sd   grass.rec.fnl.size.mean 
#                 0.8647287                 0.9269129                 0.3416982                 0.4392035                 0.4799249                 0.7390220                 0.3740750 
#     grass.rec.fnl.size.sd 
#                 0.5717532
Listing 35.69: Example: sample mean and sd of log1p-transformed fnl.size-and-hr.last-by-fire.type:cause, vectorized (Listing 35.65)
nbfL |>
  aggregate_marks(by = cbind(fnl.size, hr.last) ~ fire.type:cause, FUN = \(z) {
    c(mean = mean(z), sd = sd(z))
  }, vectorize = TRUE)
# forest.rrds.fnl.size.mean   forest.rrds.fnl.size.sd  forest.rrds.hr.last.mean    forest.rrds.hr.last.sd  grass.rrds.fnl.size.mean    grass.rrds.fnl.size.sd   grass.rrds.hr.last.mean 
#                 0.8647287                 0.9269129                 3.2775133                 1.0379506                 0.3416982                 0.4392035                 2.1677729 
#     grass.rrds.hr.last.sd  forest.rec.fnl.size.mean    forest.rec.fnl.size.sd   forest.rec.hr.last.mean     forest.rec.hr.last.sd   grass.rec.fnl.size.mean     grass.rec.fnl.size.sd 
#                 1.1694497                 0.4799249                 0.7390220                 2.7868615                 1.3290827                 0.3740750                 0.5717532 
#    grass.rec.hr.last.mean      grass.rec.hr.last.sd 
#                 1.3526997                 0.9957785

35.8 Extract via [

In an email to the author, Prof. Adrian Baddeley (Baddeley and Turner 2005) has kindly explained that in the package spatstat.geom (v3.7.0.6)

The design of the S3 class 'ppp' specifies that if the marks are a data frame with only 1 column, then the marks will be converted to a vector.

This design choice was made a long time ago, in order to avoid problems that would otherwise occur in the rest of the spatstat code.

If we were to retrospectively change the specification, we would have a lot of work to do in the rest of the code, and the documentation.

On the other hand, function grouped_ppp() (Chapter 2, Chapter 44) relies on the support of ncol-1L 'dataframe'-marks. As an ad hoc solution, the author defines

  • an (internal) derived class 'ppp_tzh' (initials of T. Zhan) that inherits from the S3 class 'ppp', and
  • an S3 method `[.ppp_tzh` that respects the ncol-1L 'dataframe'-marks. The S3 method `[.ppp_tzh` is a teeny-tiny modification of the S3 method spatstat.geom::`[.ppp`. Permision from Dr. Baddeley? GPL-2?

Listing 35.70 retains the name of the mark hladr as the column name of the ncol-1L 'dataframe'-marks (Listing 35.71), for downstream analysis.

Listing 35.70: Example: function grouped_ppp() with one mark
s_a = wrobel_lung |>
   grouped_ppp(formula = hladr ~ OS + gender + age | patient_id/image_id)
Listing 35.71: Example: support of ncol-1L 'dataframe' mark-format, name of mark retained
s_a$ppp.[[1L]] |>
  spatstat.geom::marks.ppp(drop = FALSE)
#      hladr
# 1    0.115
# 2    0.239
# 3    0.268
# ✂️ --- output truncated --- ✂️

35.9 Append to (Existing) Marks

The S3 generic syntactic sugar `append_marks<-` appends additional mark(s) to the existing marks. Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.11),

Table 35.11: S3 methods of groupedHyperframe::`append_marks<-` (v0.3.4)
visible isS4
append_marks<-.ppp TRUE FALSE
append_marks<-.psp TRUE FALSE
append_marks<-.tess TRUE FALSE

The S3 method `append_marks<-.ppp` appends additional mark(s) to (the existing marks of) a point-pattern. Table 35.12 summarizes the differences of the S3 methods `append_marks<-.ppp` versus spatstat.geom::`marks<-.ppp` (v3.7.0.6).

Table 35.12: Functions `append_marks<-.ppp` versus `marks<-.ppp`
`append_marks<-.ppp` `marks<-.ppp`
Existing Mark(s) appends additional mark(s) to existing mark(s) overwrites existing mark(s) using additional mark(s), e.g., Listing 35.75
Number of Points denoted by dot (.) user needs to obtain manually using function npoints.ppp, e.g., Listing 35.73, Listing 35.75

Listing 35.72 appends a random log-normal mark to the point-pattern vesicles (Section 9.24) without any existing mark. Listing 35.73 creates identical return as Listing 35.72 using the S3 method spatstat.geom::`marks<-.ppp`.

Listing 35.72: Example: function `append_marks<-.ppp`, no existing marks
ves = spatstat.data::vesicles
set.seed(12); append_marks(ves) = quote(rlnorm(n = .))
ves
# Marked planar point pattern: 37 points
# marks are numeric, of storage type  'double'
# window: polygonal boundary
# enclosing rectangle: [22.6796, 586.2292] x [11.9756, 1030.7] nm
Listing 35.73: Review: function spatstat.geom::`marks<-.ppp`, no existing marks
Code
suppressPackageStartupMessages(library(spatstat.geom)) 
# to put function spatstat.geom::`marks<-.ppp` on search path
ves. = spatstat.data::vesicles
set.seed(12); marks(ves.) = rlnorm(n = npoints.ppp(ves.))
stopifnot(identical(ves, ves.))

Listing 35.74 appends a random negative-binomial mark to the existing numeric mark in the point-pattern spruces (Section 9.21). Listing 35.75 does not create identical return as Listing 35.74, as the S3 method spatstat.geom::`marks<-.ppp` overwrites the existing mark.

Listing 35.74: Example: function `append_marks<-.ppp`, existing numeric marks
spru = spatstat.data::spruces
set.seed(23); append_marks(spru) = quote(rnbinom(n = ., size = 4, prob = .3))
spru
# Marked planar point pattern: 134 points
# Mark variables: m1, m2 
# window: rectangle = [0, 56] x [0, 38] metres
Listing 35.75: Review: function spatstat.geom::`marks<-.ppp`, existing numeric marks
Code
suppressPackageStartupMessages(library(spatstat.geom))
spru. = spatstat.data::spruces
set.seed(23); marks(spru.) = rnbinom(n = npoints.ppp(spru.), size = 4, prob = .3)
spru.
# Marked planar point pattern: 134 points
# marks are numeric, of storage type  'integer'
# window: rectangle = [0, 56] x [0, 38] metres

Listing 35.76 appends a random log-normal mark to the existing multi-type mark in the point-pattern ants (Section 9.2).

Listing 35.76: Example: function `append_marks<-.ppp`, existing multi-type marks
ant = spatstat.data::ants
set.seed(42); append_marks(ant) = quote(rlnorm(n = .))
ant
# Marked planar point pattern: 97 points
# Mark variables: m1, m2 
# window: polygonal boundary
# enclosing rectangle: [-25, 803] x [-49, 717] units (one unit = 0.5 feet)

Listing 35.77 appends a random log-normal mark to the three existing marks of the point-pattern gorillas (Section 9.13). The new mark is automatically named m4.

Listing 35.77: Example: function `append_marks<-.ppp`, existing 'dataframe' marks
goril_a = spatstat.data::gorillas
set.seed(33); append_marks(goril_a) = quote(rlnorm(n = .))
goril_a
# Marked planar point pattern: 647 points
# Mark variables: group, season, date, m4 
# window: polygonal boundary
# enclosing rectangle: [580457.9, 585934] x [674172.8, 678739.2] metres

Listing 35.78 appends two random log-normal marks, with user-specified mark names, to the three existing marks of the point-pattern gorillas (Section 9.13).

Listing 35.78: Example: function `append_marks<-.ppp`, existing 'dataframe' marks, multiple new marks
goril_b = spatstat.data::gorillas
set.seed(33); append_marks(goril_b) = replicate(n = 2L, expr = rlnorm(n = .), simplify = FALSE) |>
  setNames(nm = c('new1', 'new2')) |>
  quote()
goril_b
# Marked planar point pattern: 647 points
# Mark variables: group, season, date, new1, new2 
# window: polygonal boundary
# enclosing rectangle: [580457.9, 585934] x [674172.8, 678739.2] metres

35.10 Default \(r_\text{max}\)

The S3 generic function .rmax() provides the default \(r_\text{max}\) used in functions from package spatstat.explore (v3.7.0.4) that return a function-value-table (fv.object, Chapter 19), i.e., the workhorse functions in Table 35.22 and Table 35.24. Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.13),

Table 35.13: S3 methods of groupedHyperframe::.rmax (v0.3.4)
visible isS4
.rmax.fv TRUE FALSE
.rmax.hyperframe TRUE FALSE
.rmax.ppp TRUE FALSE
.rmax.ppplist TRUE FALSE

The S3 method .rmax.ppp() finds the default \(r_\text{max}\) used by various functions applicable to a point-pattern and returning a function-value-table. It is

Table 35.14: an off-label use of functions spatstat.explore::rmax.rule() and spatstat.geom::handle.r.b.args()
Table 35.14: Default \(r_\text{max}\) used in functions from package spatstat.explore (v3.7.0.4) that return an fv.object
Function from package spatstat.explore Call of spatstat.explore::rmax.rule Default \(r_\text{max}\) via .rmax()
markcorr, the workhorse function of Emark and Vmark, markvario rmax.rule(fun = 'K', ...) .rmax(fun = 'K')
Kinhom, the workhorse function of Kmark and markcorrint rmax.rule(fun = 'K', ...) .rmax(fun = 'K')
Kcross, and its workhorse functions Kest and Kmulti rmax.rule(fun = 'K', ...) .rmax(fun = 'K') or .rmax(fun = 'K', i, j)
Gcross, and its workhorse functions Gest and Gmulti rmax.rule(fun = 'G', ...) .rmax(fun = 'G') or .rmax(fun = 'G', i, j)
Jcross, and its workhorse functions Jest and Jmulti rmax.rule(fun = 'J', ...) .rmax(fun = 'J') or .rmax(fun = 'J', i, j)
Listing 35.79: Advanced: function .rmax.ppp() for markcorr() on numeric mark
spatstat.data::spruces |>
  spatstat.explore::markcorr() |>
  .rmax.fv() |>
  identical(y = spatstat.data::spruces |> .rmax.ppp(fun = 'K')) |>
  stopifnot()
Listing 35.80: Advanced: function .rmax.ppp() for markcorr() on numeric marks in 'dataframe' mark-format
spatstat.data::finpines |>
  spatstat.explore::markcorr() |>
  vapply(FUN = .rmax.fv, FUN.VALUE = NA_real_) |>
  vapply(
    FUN = identical, 
    y = spatstat.data::finpines |> .rmax(fun = 'K'), 
    FUN.VALUE = NA
  ) |>
  stopifnot()
Listing 35.81: Advanced: function .rmax.ppp() for Gcross() on multi-type mark, character levels
spatstat.data::ants |>
  spatstat.explore::Gcross(i = 'Messor', j = 'Cataglyphis') |>
  .rmax.fv() |>
  identical(
    y = spatstat.data::ants |> 
      .rmax.ppp(fun = 'G', i = 'Messor', j = 'Cataglyphis')
  ) |>
  stopifnot()

35.11 \(k\)-Means Clustering

Function kmeans.ppp() performs \(k\)-means clustering (Hartigan and Wong 1979) on a point-pattern. This is a “pseudo” S3 method, as the workhorse function stats::kmeans() shipped with R version 4.5.2 (2025-10-31) is not an S3 generic function. Note that to reproduce a \(k\)-means clustering using stats::kmeans(), readers must set the .Random.seed beforehand.

Function kmeans.ppp() has parameters

  • formula, \(x\)- and/or \(y\)- coordinate(s) and/or (one or more of the) numeric marks
  • (optional) centers, number of clusters
  • (optional) clusterSize, “expected” number of points per cluster.

User should specify one of the two optional parameters centers and clusterSize. If both are specified, then parameter clusterSize takes priority and parameter centers is ignored.

Function kmeans.ppp() returns an object of S3 class 'pppkm', which inherits from the class 'ppp' and is assigned with additional attributes,

  • attr(.,'f'), a factor indicating the \(k\)-means clustering indices.

Package groupedHyperframe (v0.3.4) implements the following S3 methods to the class 'pppkm' (Table 35.15), most of which are straightforward extensions of the S3 methods for the class 'ppp' (Listing 35.2).

Table 35.15: S3 methods groupedHyperframe::*.pppkm (v0.3.4)
visible generic isS4
plot.pppkm TRUE base::plot FALSE
print.pppkm TRUE base::print FALSE
split.pppkm TRUE base::split FALSE

35.11.1 Print & Plot

Listing 35.82 performs 3L-means clustering on the \(x\)- and \(y\)-coordinates-only point-pattern vesicles (Section 9.24) by the \(x\)-coordinates.

Listing 35.82: Example: function kmeans.ppp(); cluster vesicles by ~ x
set.seed(12); spatstat.data::vesicles |> 
  kmeans.ppp(formula = ~ x, centers = 3L)
# Planar point pattern: 37 points
# window: polygonal boundary
# enclosing rectangle: [22.6796, 586.2292] x [11.9756, 1030.7] nm
# with k-means clustering of 10, 15, 12 points

Listing 35.83 performs 3L-means clustering on vesicles (Section 9.24) by the \(x\)- and \(y\)-coordinates. Figure 35.1 visualizes the \(x\)- and \(y\)-coordinates and the 3L-means clustering indices.

Listing 35.83: Example: function kmeans.ppp(); cluster vesicles by ~ x + y
set.seed(21); vesicles_k2 = spatstat.data::vesicles |> 
  kmeans.ppp(formula = ~ x + y, centers = 3L)
vesicles_k2
# Planar point pattern: 37 points
# window: polygonal boundary
# enclosing rectangle: [22.6796, 586.2292] x [11.9756, 1030.7] nm
# with k-means clustering of 11, 10, 16 points
Listing 35.84: Figure: function plot.pppkm(); cluster vesicles by ~ x + y
Code
par(mar = c(0,0,1,0))
vesicles_k2 |>
  plot()
Figure 35.1: Cluster vesicles by ~ x + y

Listing 35.85 performs \(k\)-means clustering on vesicles (Section 9.24) by the \(x\)- and \(y\)-coordinates, with an expected cluster size of 10L.

Listing 35.85: Example: function kmeans.ppp(); cluster vesicles by ~ x + y and parameter clusterSize
set.seed(43); spatstat.data::vesicles |> 
  kmeans.ppp(formula = ~ x + y, clusterSize = 10L)
# Planar point pattern: 37 points
# window: polygonal boundary
# enclosing rectangle: [22.6796, 586.2292] x [11.9756, 1030.7] nm
# with k-means clustering of 9, 10, 12, 6 points

Listing 35.86 - Listing 35.87 perform 3L-means clustering in the point-pattern spruces (Section 9.21) with 'vector' mark-format.

Listing 35.86: Example: function kmeans.ppp(); cluster spruces by ~ x + marks
set.seed(30); spatstat.data::spruces |> 
  kmeans.ppp(formula = ~ x + marks, centers = 3L)
# Marked planar point pattern: 134 points
# marks are numeric, of storage type  'double'
# window: rectangle = [0, 56] x [0, 38] metres
# with k-means clustering of 47, 39, 48 points
Listing 35.87: Example: function kmeans.ppp(); cluster spruces by ~ x + y + marks
set.seed(62); spatstat.data::spruces |> 
  kmeans.ppp(formula = ~ x + y + marks, centers = 3L)
# Marked planar point pattern: 134 points
# marks are numeric, of storage type  'double'
# window: rectangle = [0, 56] x [0, 38] metres
# with k-means clustering of 40, 38, 56 points

Listing 35.88 - Listing 35.89 perform 3L-means clustering in the point-pattern finpines (Section 9.11) with 'dataframe' mark-format.

Listing 35.88: Example: function kmeans.ppp(); cluster finpines by ~ x + y + height
set.seed(18); spatstat.data::finpines |> 
  kmeans.ppp(formula = ~ x + y + height, centers = 3L)
# Marked planar point pattern: 126 points
# Mark variables: diameter, height 
# window: rectangle = [-5, 5] x [-8, 2] metres
# with k-means clustering of 38, 42, 46 points
Listing 35.89: Example: function kmeans.ppp(); cluster finpines by ~ x + diameter + height
set.seed(20); spatstat.data::finpines |> 
  kmeans.ppp(formula = ~ x + diameter + height, centers = 3L)
# Marked planar point pattern: 126 points
# Mark variables: diameter, height 
# window: rectangle = [-5, 5] x [-8, 2] metres
# with k-means clustering of 37, 45, 44 points

35.11.2 Split by \(k\)-Means Clustering

Package groupedHyperframe (v0.3.4) implements the following S3 methods of the generic function base::split() (Table 35.16),

Table 35.16: S3 methods of base::split (v4.5.2)
visible isS4
split.hyperframekm TRUE FALSE
split.pppkm TRUE FALSE
split.pppkmlist TRUE FALSE

The S3 method split.pppkm() (Listing 35.90) splits the \(k\)-means clustered point-pattern flu$pattern[[1L]] (Section 9.12) by its \(k\)-means clustering indices.

Listing 35.90: Example: function split.pppkm()
Code
set.seed(15); spatstat.data::flu$pattern[[1L]] |> 
  kmeans.ppp(formula = ~ x + y, centers = 3L) |>
  split()
# Point pattern split by factor 
# 
# 1:
# Marked planar point pattern: 169 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm
# 
# 2:
# Marked planar point pattern: 157 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm
# 
# 3:
# Marked planar point pattern: 145 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm

35.12 Pairwise Tjøstheim (1978)’s Coefficient

The S3 generic function pairwise_cor_spatial() calculates the nonparametric, rank-based, Tjøstheim (1978)’s correlation coefficients (Hubert and Golledge 1982) in a pairwise-combination fashion, using the workhorse function SpatialPack::cor.spatial() (Vallejos, Osorio, and Bevilacqua 2020, v0.4.1). Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.17),

Table 35.17: S3 methods of groupedHyperframe::pairwise_cor_spatial (v0.3.4)
visible isS4
pairwise_cor_spatial.ppp TRUE FALSE
pairwise_cor_spatial.ppplist TRUE FALSE

The S3 method pairwise_cor_spatial.ppp() finds the nonparametric Tjøstheim (1978)’s correlation coefficients from the pairwise-combinations of all numeric marks in a point-pattern, and returns an object of S3 class 'pairwise_cor_spatial', which inherits from the class 'dist' defined in package stats shipped with R version 4.5.2 (2025-10-31). Such inheritance, as well as the intrinsic similarity in data structure (Table 35.18), enables us to make use of the S3 methods to class 'dist', e.g., stats:::print.dist(), stats:::as.matrix.dist(), stats:::format.dist() and stats:::labels.dist(). Package groupedHyperframe (v0.3.4) implements the following S3 methods to the class 'pairwise_cor_spatial' (Table 35.19),

Table 35.18: Similarity in Data Structure, 'pairwise_cor_spatial' & 'dist'
'pairwise_cor_spatial' object 'dist' object
Constant diagonal Values of 1; i.e., perfect correlation of 0; i.e., zero distance
Table 35.19: S3 methods groupedHyperframe::*.pairwise_cor_spatial (v0.3.4)
visible from generic isS4
as.matrix.pairwise_cor_spatial TRUE groupedHyperframe base::as.matrix FALSE

The S3 method as.matrix.pairwise_cor_spatial() returns a matrix of pairwise Tjøstheim (1978)’s coefficients with diagonal values of 1. This matrix, however, is not a correlation matrix, because Tjøstheim (1978)’s correlation coefficient

  • is nonparametric, i.e., there is no definition of the corresponding covariance, standard deviation sd, nor the conversion cov2cor method;
  • does not provide a mathematical mechanism to ensure that this matrix is positive definite.

Listing 35.91 creates a pairwise_cor_spatial object from the point-pattern finpines (Section 9.11).

Listing 35.91: Example: function pairwise_cor_spatial.ppp()
finpines_paircor = spatstat.data::finpines |>
  pairwise_cor_spatial()

Listing 35.92 prints finpines_paircor (Listing 35.91) using the S3 method stats:::print.dist().

Listing 35.92: A pairwise_cor_spatial object finpines_paircor (Listing 35.91)
finpines_paircor
#         diameter
# height 0.7287879

Listing 35.93 converts finpines_paircor (Listing 35.91) into a matrix.

Listing 35.93: Example: function as.matrix.pairwise_cor_spatial() (Listing 35.91)
finpines_paircor |> 
  as.matrix()
#           diameter    height
# diameter 1.0000000 0.7287879
# height   0.7287879 1.0000000

35.13 Random Re-Labelling Envelope Residual & Test

The S3 generic function rlabelRes() finds the residual form of the random re-labelling envelope (Baddeley et al. 2014; Myllymäki and Mrkvička 2024; Myllymäki et al. 2016). Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.20),

Table 35.20: S3 methods of groupedHyperframe::rlabelRes (v0.3.4)
visible isS4
rlabelRes.hyperframe TRUE FALSE
rlabelRes.ppp TRUE FALSE
rlabelRes.ppplist TRUE FALSE

The S3 method rlabelRes.ppp() is a simple wrapper of the functions

The S3 method rlabelRes.ppp() returns a 'curve_set' (Chapter 16).

Listing 35.94 performs the random re-labelling envelope residual and test on the point-pattern anemones (Section 9.1).

Listing 35.94: Example: function rlabelRes.ppp(), with Kmark
set.seed(52); spatstat.data::anemones |>
  rlabelRes(fun = spatstat.explore::Kmark) |>
  GET::global_envelope_test()
# Global envelope test (1d):
#  * Based on the measure: "erl"
#  * 95% global envelope
#  * p-value of the global test: 0.01
#  * Significance level of the global test: 0.05
#  * Number of r with observed function outside the envelope: 443
#  * Total number of argument values r                      : 513
# The object contains: 
# $r - Argument values                       :  num [1:513] 0 0.0879 0.1758 0.2637 0.3516 ...
# $obs - Observed function                   :  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $central - Central function                :  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $lo - Lower boundary of the global envelope:  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $hi - Upper boundary of the global envelope:  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...

Listing 35.95 performs the random re-labelling envelope residual and test on the point-pattern anemones (Section 9.1).

Listing 35.95: Example: function rlabelRes.ppp(), with Kmark and f = `*`
set.seed(52); spatstat.data::anemones |>
  rlabelRes(fun = spatstat.explore::Kmark, f = `*`) |>
  GET::global_envelope_test()
# Global envelope test (1d):
#  * Based on the measure: "erl"
#  * 95% global envelope
#  * p-value of the global test: 0.01
#  * Significance level of the global test: 0.05
#  * Number of r with observed function outside the envelope: 443
#  * Total number of argument values r                      : 513
# The object contains: 
# $r - Argument values                       :  num [1:513] 0 0.0879 0.1758 0.2637 0.3516 ...
# $obs - Observed function                   :  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $central - Central function                :  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $lo - Lower boundary of the global envelope:  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $hi - Upper boundary of the global envelope:  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...

Listing 35.96 performs the random re-labelling envelope residual and test on the point-pattern ant (Section 9.2).

Listing 35.96: Example: function rlabelRes.ppp(), with Gcross
set.seed(12); spatstat.data::ants |>
  rlabelRes(fun = spatstat.explore::Gcross) |>
  GET::global_envelope_test()
# Global envelope test (1d):
#  * Based on the measure: "erl"
#  * 95% global envelope
#  * p-value of the global test: 0.02
#  * Significance level of the global test: 0.05
#  * Number of r with observed function outside the envelope: 95
#  * Total number of argument values r                      : 513
# The object contains: 
# $r - Argument values                       :  num [1:513] 0 0.297 0.594 0.891 1.188 ...
# $obs - Observed function                   :  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $central - Central function                :  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $lo - Lower boundary of the global envelope:  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...
# $hi - Upper boundary of the global envelope:  num [1:513] 0 0 0 0 0 0 0 0 0 0 ...

The random re-labelling envelope residual and test require calling the S3 generic function rlabelRes() and

instead of having one single “combined” function, due to the difficulty of manipulating the formal arguments of functions envelope.ppp() (v3.7.0.4) and global_envelope_test() (v1.0.7). Specifically (Listing 35.97),

  1. the parameters alternative of function envelope.ppp() versus of function global_envelope_test() have different meanings;
  2. it’s almost impossible to determine whether some parameter(s) should be sent to the dynamic-dots ... of function envelope.ppp() or global_envelope_test().
Listing 35.97: Advanced: Formal arguments of envelope.ppp & global_envelope_test()
ag1 = spatstat.explore::envelope.ppp |> 
  formalArgs()
ag2 = GET::global_envelope_test |>
  formalArgs()
intersect(ag1, ag2)
# [1] "..."         "alternative"

35.14 Batch Process on Eligible Marks

Table 35.22, Table 35.24 and Table 35.25 delve into the intricate mechanics of the batch processes (Section 2.2), offering insights that will resonate with advanced R practitioners. Package groupedHyperframe (v0.3.4) implements the following S3 methods (Table 35.21),

Table 35.21: S3 methods groupedHyperframe::Emark_.*, groupedHyperframe::Vmark_.*, groupedHyperframe::markcorr_.*, groupedHyperframe::markvario_.*, groupedHyperframe::Gcross_.*, groupedHyperframe::Kcross_.*, groupedHyperframe::Jcross_.*, groupedHyperframe::Lcross_.*, groupedHyperframe::markconnect_.*, groupedHyperframe::nncross_.* (v0.3.4)
visible generic isS4
Emark_.hyperframe TRUE groupedHyperframe::Emark_ FALSE
Emark_.ppp TRUE groupedHyperframe::Emark_ FALSE
Emark_.ppplist TRUE groupedHyperframe::Emark_ FALSE
Vmark_.hyperframe TRUE groupedHyperframe::Vmark_ FALSE
Vmark_.ppp TRUE groupedHyperframe::Vmark_ FALSE
Vmark_.ppplist TRUE groupedHyperframe::Vmark_ FALSE
markcorr_.hyperframe TRUE groupedHyperframe::markcorr_ FALSE
markcorr_.ppp TRUE groupedHyperframe::markcorr_ FALSE
markcorr_.ppplist TRUE groupedHyperframe::markcorr_ FALSE
markvario_.hyperframe TRUE groupedHyperframe::markvario_ FALSE
markvario_.ppp TRUE groupedHyperframe::markvario_ FALSE
markvario_.ppplist TRUE groupedHyperframe::markvario_ FALSE
Gcross_.hyperframe TRUE groupedHyperframe::Gcross_ FALSE
Gcross_.ppp TRUE groupedHyperframe::Gcross_ FALSE
Gcross_.ppplist TRUE groupedHyperframe::Gcross_ FALSE
Kcross_.hyperframe TRUE groupedHyperframe::Kcross_ FALSE
Kcross_.ppp TRUE groupedHyperframe::Kcross_ FALSE
Kcross_.ppplist TRUE groupedHyperframe::Kcross_ FALSE
Jcross_.hyperframe TRUE groupedHyperframe::Jcross_ FALSE
Jcross_.ppp TRUE groupedHyperframe::Jcross_ FALSE
Jcross_.ppplist TRUE groupedHyperframe::Jcross_ FALSE
Lcross_.hyperframe TRUE groupedHyperframe::Lcross_ FALSE
Lcross_.ppp TRUE groupedHyperframe::Lcross_ FALSE
Lcross_.ppplist TRUE groupedHyperframe::Lcross_ FALSE
markconnect_.hyperframe TRUE groupedHyperframe::markconnect_ FALSE
markconnect_.ppp TRUE groupedHyperframe::markconnect_ FALSE
markconnect_.ppplist TRUE groupedHyperframe::markconnect_ FALSE
nncross_.hyperframe TRUE groupedHyperframe::nncross_ FALSE
nncross_.ppp TRUE groupedHyperframe::nncross_ FALSE
nncross_.ppplist TRUE groupedHyperframe::nncross_ FALSE

35.14.1 Function-Value-Table from Numeric Mark(s)

The S3 methods in Table 35.22 are user-friendly wrappers of the low-level utility function ppp_numeric2fv(). These S3 methods

  • identify all eligible numeric marks in the input point-pattern;
  • apply the workhorse function from package spatstat.explore (v3.7.0.4) per numeric mark;
  • return an fvlist (Chapter 20) named by the numeric mark(s).
Table 35.22: Batch processes; eligible numeric marks to function-value-tables
Batch Process Workhorse function in Package spatstat.explore
Emark_.ppp(), Vmark_.ppp(), e.g., Listing 35.99, Listing 35.100, Listing 35.98 Emark and Vmark, conditional mean \(E(r)\) and variance \(V(r)\), diagnostics for dependence between the points and the marks (Schlather, Ribeiro, and Diggle 2003)
markcorr_.ppp() markcorr, marked correlation \(k_{mm}(r)\) or generalized mark correlation \(k_f(r)\) (Stoyan and Stoyan 1994)
markvario_.ppp() markvario, mark variogram \(\gamma(r)\) (Wälder and Stoyan 1996)
Kmark_.ppp() Kmark, mark-weighted \(K_f(r)\) function (Penttinen, Stoyan, and Henttonen 1992)

Listing 35.98 showcases the exception handling of the point-pattern ants (Section 9.2) without any numeric mark.

Listing 35.98: Exception: function Emark_.ppp(), no numeric mark
spatstat.data::ants |> 
  Emark_() |>
  is.null() |> stopifnot()

Listing 35.99 finds the conditional mean \(E(r)\) of the eligible numeric mark area in the point-pattern betacells (Section 9.4).

Listing 35.99: Example: function Emark_.ppp()
spatstat.data::betacells |>
  Emark_()
# An 'fvlist' of 1 fv.objects E(r) 
# Name(s): area 
# Available rmax: 187.5 
# Minimum Legal rmax: 187.5

Listing 35.100 shows that a generic name m is used for the 'vector' mark-format of the point-pattern spruces (Section 9.21).

Listing 35.100: Example: function Emark_.ppp(), 'vector' mark-format
spatstat.data::spruces |> 
  Emark_()
# An 'fvlist' of 1 fv.objects E(r) 
# Name(s): m 
# Available rmax: 9.5 
# Minimum Legal rmax: 9.5

A similar batch mechanism exists in package spatstat.explore (v3.7.0.4) for ppp.object with 'dataframe' mark-format. Table 35.23 shows the difference and connection between the batch mechanism in Table 35.22 versus that in package spatstat.explore. Listing 35.101 - Listing 35.103 illustrate them using a point-pattern finpines (Section 9.11) with two numeric marks.

Table 35.23: Batch mechanism for point-patterns with 'dataframe' mark-format
In Package spatstat.explore (v3.7.0.4) In Table 35.22
Input ppp.object Require all marks be numeric Select the eligible numeric marks
Output An anylist (Chapter 14) of fv.objects An fvlist (Chapter 20)
Listing 35.101: Advanced: function markcorr_.ppp() versus spatstat.explore::markcorr()
spatstat.data::finpines |> 
  markcorr_() |>
  mapply(
    FUN = identical, 
    y = spatstat.data::finpines |> spatstat.explore::markcorr()
  ) |> 
  stopifnot()
Listing 35.102: Advanced: function Emark_.ppp() versus spatstat.explore::Emark()
spatstat.data::finpines |> 
  Emark_() |>
  mapply(
    FUN = identical, 
    y = spatstat.data::finpines |> spatstat.explore::Emark()
  ) |>
  stopifnot()
Listing 35.103: Advanced: function Vmark_.ppp() versus spatstat.explore::Vmark()
spatstat.data::finpines |> 
  Vmark_() |>
  mapply(
    FUN = identical, 
    y = spatstat.data::finpines |> spatstat.explore::Vmark()
  ) |>
  stopifnot()

35.14.2 Function-Value-Table from Multi-Type Mark(s)

The S3 methods in Table 35.24 are user-friendly wrappers of the low-level utility function ppp_multitype2fv(). These S3 methods

  • identify all eligible multi-type marks in the input point-pattern;
  • apply the workhorse function from package spatstat.explore (v3.7.0.4) per multi-type mark;
  • return an fvlist (Chapter 20), named by the multi-type mark(s).
Table 35.24: Batch processes; eligible multi-type marks to fvlists
Batch Process Workhorse function in Package spatstat.explore
Gcross_.ppp(), e.g., Listing 35.104 Gcross, multi-type nearest-neighbor distance \(G_{ij}(r)\)
Kcross_.ppp() Kcross, multi-type \(K_{ij}(r)\)
Jcross_.ppp() Jcross, multi-type \(J_{ij}(r)\) (Van Lieshout and Baddeley 1999)
Lcross_.ppp() Lcross, multi-type \(L_{ij}(r)=\sqrt{\frac{K_{ij}(r)}{\pi}}\)
markconnect_.ppp() markconnect, multi-type \(p_{ij}(r)\)

Listing 35.104 finds the multi-type nearest-neighbor distance \(G_{ij}(r)\) from the marks 'off' to 'on' in the eligible multi-type mark type in the point-pattern betacells (Section 9.4).

Listing 35.104: Example: function Gcross_.ppp(., i = 'off', j = 'on')
spatstat.data::betacells |>
  Gcross_(i = 'off', j = 'on')
# An 'fvlist' of 1 fv.objects G[off,on](r) 
# Name(s): type 
# Available rmax: 204.686521588743 
# Minimum Legal rmax: 204.7

35.14.3 Distance from Multi-Type Mark(s)

The S3 methods in Table 35.25 are user-friendly wrappers of the low-level utility function ppp2dist(). These S3 methods

  • identify all eligible multi-type marks in the input point-pattern;
  • apply the workhorse function per multi-type mark;
  • return a numeric vector-list (vectorlist, Chapter 42), named by the multi-type mark(s).
Table 35.25: Batch processes; eligible multi-type marks to numeric-vectors
Batch Process Workhorse function
nncross_.ppp(), e.g., Listing 35.105 - Listing 35.110 .nncross() (Section 35.6), nearest neighbor distance

Listing 35.105 applies the function .nncross() (Section 35.6) to the multi-type mark type in the point-pattern betacells (Section 9.4), which contains (at least) the two levels of 'off' and 'on'.

Listing 35.105: Example: function nncross_.ppp(., i = 'off', j = 'on')
spatstat.data::betacells |>
  nncross_(i = 'off', j = 'on')
# A 'vectorlist' of 1 vectors 
# Name(s): type 
# Storage Mode: numeric 
# Individual Vector Length: 70 
# Suffix: nncross

Listing 35.106 applies the function .nncross() (Section 35.6) to the multi-type mark group in the point-pattern gorillas (Section 9.13), which contains (at least) the two levels of 'major' and 'minor'.

Listing 35.106: Example: function nncross_.ppp(., i = 'major', j = 'minor')
spatstat.data::gorillas |>
  nncross_(i = 'major', j = 'minor')
# A 'vectorlist' of 1 vectors 
# Name(s): group 
# Storage Mode: numeric 
# Individual Vector Length: 350 
# Suffix: nncross

Listing 35.107 applies the function .nncross() (Section 35.6) to the multi-type mark season in the point-pattern gorillas (Section 9.13), which contains (at least) the two levels of 'rainy' and 'dry'.

Listing 35.107: Example: function nncross_.ppp(., i = 'rainy', j = 'dry')
spatstat.data::gorillas |>
  nncross_(i = 'rainy', j = 'dry')
# A 'vectorlist' of 1 vectors 
# Name(s): season 
# Storage Mode: numeric 
# Individual Vector Length: 372 
# Suffix: nncross

Listing 35.108 showcases the exception handling when no eligible multi-type mark exists in the point-pattern gorillas (Section 9.13) that contains both levels 'alpha' and 'beta'.

Listing 35.108: Exception: function nncross_.ppp(., i = 'male', j = 'female')
spatstat.data::gorillas |>
  nncross_(i = 'male', j = 'female') |>
  is.null() |> stopifnot()

Listing 35.109 uses a generic name m for the 'vector' mark-format of the point-pattern ants (Section 9.2).

Listing 35.109: Example: function nncross_.ppp(), 'vector' mark-format
spatstat.data::ants |> 
  nncross_(i = 'Cataglyphis', j = 'Messor')
# A 'vectorlist' of 1 vectors 
# Name(s): m 
# Storage Mode: numeric 
# Individual Vector Length: 29 
# Suffix: nncross

Listing 35.110 showcases the exception handling with the point-pattern spruces (Section 9.21), which does not contain a multi-type mark.

Listing 35.110: Exception: function nncross_.ppp(), no multi-type mark
spatstat.data::spruces |> 
  nncross_() |>
  is.null() |> stopifnot()