26  hyperframe

Function spatstat.geom::hyperframe() creates a hyper data frame, i.e., an R object of S3 class 'hyperframe'.

The S3 generic function spatstat.geom::as.hyperframe() converts R objects of various classes into a hyper data frame. Listing 26.1 summarizes the S3 methods for the generic function as.hyperframe() in the spatstat.* family of packages,

Listing 26.1: S3 methods spatstat.*::as.hyperframe.*
Code
suppressPackageStartupMessages(library(spatstat))
.S3methods(generic.function = 'as.hyperframe', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = grepl(pattern = '^spatstat\\.', x = from))
#                          visible          from       generic  isS4
# as.hyperframe.anylist       TRUE spatstat.geom as.hyperframe FALSE
# as.hyperframe.data.frame    TRUE spatstat.geom as.hyperframe FALSE
# as.hyperframe.default       TRUE spatstat.geom as.hyperframe FALSE
# as.hyperframe.hyperframe    TRUE spatstat.geom as.hyperframe FALSE
# as.hyperframe.listof        TRUE spatstat.geom as.hyperframe FALSE
# as.hyperframe.ppx           TRUE spatstat.geom as.hyperframe FALSE

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

Listing 26.2: S3 methods spatstat.*::*.hyperframe
Code
suppressPackageStartupMessages(library(spatstat))
.S3methods(class = 'hyperframe', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = grepl(pattern = '^spatstat\\.', x = from))
#                          visible          from       generic  isS4
# [.hyperframe                TRUE spatstat.geom             [ FALSE
# [[.hyperframe               TRUE spatstat.geom            [[ FALSE
# [[<-.hyperframe             TRUE spatstat.geom          [[<- FALSE
# [<-.hyperframe              TRUE spatstat.geom           [<- FALSE
# $.hyperframe                TRUE spatstat.geom             $ FALSE
# $<-.hyperframe              TRUE spatstat.geom           $<- FALSE
# as.data.frame.hyperframe    TRUE spatstat.geom as.data.frame FALSE
# as.hyperframe.hyperframe    TRUE spatstat.geom as.hyperframe FALSE
# as.list.hyperframe          TRUE spatstat.geom       as.list FALSE
# cbind.hyperframe            TRUE spatstat.geom         cbind FALSE
# dim.hyperframe              TRUE spatstat.geom           dim FALSE
# dimnames.hyperframe         TRUE spatstat.geom      dimnames FALSE
# dimnames<-.hyperframe       TRUE spatstat.geom    dimnames<- FALSE
# edit.hyperframe             TRUE spatstat.geom          edit FALSE
# head.hyperframe             TRUE spatstat.geom          head FALSE
# is.na.hyperframe            TRUE spatstat.geom         is.na FALSE
# names.hyperframe            TRUE spatstat.geom         names FALSE
# names<-.hyperframe          TRUE spatstat.geom       names<- FALSE
# plot.hyperframe             TRUE spatstat.geom          plot FALSE
# print.hyperframe            TRUE spatstat.geom         print FALSE
# rbind.hyperframe            TRUE spatstat.geom         rbind FALSE
# row.names.hyperframe        TRUE spatstat.geom     row.names FALSE
# row.names<-.hyperframe      TRUE spatstat.geom   row.names<- FALSE
# split.hyperframe            TRUE spatstat.geom         split FALSE
# split<-.hyperframe          TRUE spatstat.geom       split<- FALSE
# str.hyperframe              TRUE spatstat.geom           str FALSE
# subset.hyperframe           TRUE spatstat.geom        subset FALSE
# summary.hyperframe          TRUE spatstat.geom       summary FALSE
# tail.hyperframe             TRUE spatstat.geom          tail FALSE
# with.hyperframe             TRUE spatstat.geom          with FALSE

The examples in Chapter 26 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"    "stats"            
# [64] "systemfonts"       "tensor"            "textshaping"       "tibble"            "tidyselect"        "tools"             "utils"             "vctrs"             "viridisLite"      
# [73] "xfun"              "yaml"

Table 26.1 summarizes the S3 methods for the class 'hyperframe' in package groupedHyperframe (v0.3.2.20251225),

Table 26.1: S3 methods groupedHyperframe::*.hyperframe (v0.3.2.20251225)
visible generic isS4
.disrecommend2theo.hyperframe TRUE groupedHyperframe::.disrecommend2theo FALSE
.illegal2theo.hyperframe TRUE groupedHyperframe::.illegal2theo FALSE
.rmax.hyperframe TRUE groupedHyperframe::.rmax FALSE
aggregate_marks.hyperframe TRUE groupedHyperframe::aggregate_marks FALSE
aggregate.hyperframe TRUE stats::aggregate FALSE
as.groupedHyperframe.hyperframe TRUE groupedHyperframe::as.groupedHyperframe FALSE
attr_.hyperframe TRUE groupedHyperframe::attr_ FALSE
cumvtrapz.hyperframe TRUE groupedHyperframe::cumvtrapz FALSE
Emark_.hyperframe TRUE groupedHyperframe::Emark_ FALSE
Gcross_.hyperframe TRUE groupedHyperframe::Gcross_ FALSE
global_envelope_test_.hyperframe TRUE groupedHyperframe::global_envelope_test_ FALSE
Jcross_.hyperframe TRUE groupedHyperframe::Jcross_ FALSE
Kcross_.hyperframe TRUE groupedHyperframe::Kcross_ FALSE
kerndens.hyperframe TRUE groupedHyperframe::kerndens FALSE
keyval.hyperframe TRUE groupedHyperframe::keyval FALSE
Kmark_.hyperframe TRUE groupedHyperframe::Kmark_ FALSE
Lcross_.hyperframe TRUE groupedHyperframe::Lcross_ FALSE
length.hyperframe TRUE base::length FALSE
markconnect_.hyperframe TRUE groupedHyperframe::markconnect_ FALSE
markcorr_.hyperframe TRUE groupedHyperframe::markcorr_ FALSE
markvario_.hyperframe TRUE groupedHyperframe::markvario_ FALSE
nncross_.hyperframe TRUE groupedHyperframe::nncross_ FALSE
quantile.hyperframe TRUE stats::quantile FALSE
rlabelRes.hyperframe TRUE groupedHyperframe::rlabelRes FALSE
superimpose.hyperframe TRUE spatstat.geom::superimpose FALSE
Vmark_.hyperframe TRUE groupedHyperframe::Vmark_ FALSE

26.1 Examples

Listing 26.3 creates a subset of the hyper data frame flu (Section 10.10).

Listing 26.3: Data: fluM, a subset of flu (Section 10.10)
fluM = spatstat.data::flu |>
  spatstat.geom::subset.hyperframe(
    subset = (stain == 'M2-M1') & (virustype == 'wt'),
    select = c('pattern', 'frameid')
  )
fluM
# Hyperframe:
#             pattern frameid
# wt M2-M1 13   (ppp)      13
# wt M2-M1 22   (ppp)      22
# wt M2-M1 27   (ppp)      27
# wt M2-M1 43   (ppp)      43
# wt M2-M1 49   (ppp)      49
# wt M2-M1 65   (ppp)      65
# wt M2-M1 71   (ppp)      71
# wt M2-M1 84   (ppp)      84

26.2 Plot

Section 26.2 is intended as an educational handbook for beginners to package spatstat.geom (v3.6.1.16). This section does not discuss the functionality of package groupedHyperframe (v0.3.2.20251225).

The S3 method spatstat.geom::plot.hyperframe() plots the plot-able hypercolumn(s) in a hyper data frame.

Listing 26.4 deems the multi-type ppp-hypercolumn flu$pattern (Section 10.10) to be plot-able, and plots them (Figure 26.1).

Listing 26.4: Review: spatstat.geom::plot.hyperframe(); plot ppp-hypercolumn flu$pattern
par(mar = c(0,0,1,0))
spatstat.data::flu[1:2, ] |>
  spatstat.geom::plot.hyperframe()
Figure 26.1: Plot ppp-hypercolumn flu$pattern

26.3 Length

The S3 method length.hyperframe() finds the number of columns and/or hypercolumns of a hyper data frame. Table 26.2 explains its rational and similarity to other length methods in package base shipped with R version 4.5.2 (2025-10-31).

Table 26.2: Rational of S3 Method length.hyperframe()
length() on 'data.frame' length.POSIXlt() length.hyperframe()
Number of (Hyper)Columns Yes (Listing 26.5) Not Applicable Yes (Listing 26.6)
User-Perceived Length Yes, “length” as number of columns Yes (Listing 26.8) Yes, “length” as number of (hyper)columns
Internal Structure Length Yes, “length” as number of list elements No (Listing 26.9) No (Listing 26.7)

Listing 26.5 reveals that the data frame Formaldehyde from package datasets shipped with R version 4.5.2 (2025-10-31) has 2 columns, using the .Primitive S3 generic function base::length().

Listing 26.5: Review: function base::length() on data.frame
datasets::Formaldehyde |>
  length()
# [1] 2

Listing 26.6 reveals that the hyper data frame demohyper (Section 10.8) has 3 (hyper)columns. The internal structure length of a hyper data frame (Listing 26.7) is not relevant to end users and may change without notice in package spatstat.geom (v3.6.1.16).

Listing 26.6: Example: function length.hyperframe()
spatstat.data::demohyper |>
  length()
# [1] 3
Listing 26.7: Review: length of hyper data frame, internal-structure
Code
spatstat.data::demohyper |>
  unclass() |>
  length()
# [1] 8

The S3 method base::length.POSIXlt() (Listing 26.8) returns the user-perceived length of a POSIXlt object , rather than its internal structure length (Listing 26.9).

Listing 26.8: Review: length of a POSIXlt object, user-perceived
Code
tm = Sys.time() |> 
  as.POSIXlt.POSIXct(tz = 'GMT')
tm |> 
  length.POSIXlt()
# [1] 1
Listing 26.9: Review: length of a POSIXlt object, internal-structure (Listing 26.8)
Code
tm |> 
  unclass() |>
  length()
# [1] 11

26.4 Kernel Density Estimates

The S3 method kerndens.hyperframe() (Section 33.1, Table 33.2) finds the kernel density (Becker, Chambers, and Wilks 1988) estimates,

  • of the numeric-hypercolumns using the S3 method kerndens.anylist() (Section 15.1), and
  • of the numeric marks in the one-and-only-one point-pattern (ppp) hypercolumn using the S3 method kerndens.ppplist() (Section 37.2).

and appends additional numeric-hypercolumns to the input. Example has been discussed extensively in Section 3.3.4.

26.5 Quantile

The S3 method quantile.hyperframe() finds the quantiles

and appends the returned quantiles as numeric-hypercolumns to the input. Example has been discussed extensively in Section 3.3.3.

26.6 Aggregation

The S3 method aggregate.hyperframe()

  • splits (Section 15.5), according to the grouping level specified in the parameter by,
    • the hypercolumn(s) that are ppplist(s) (Chapter 37) into list(s) of ppplist;
    • the hypercolumn(s) that are imlist(s) (Chapter 29) into list(s) of imlist;
    • the hypercolumn(s) that are fvlist(s) (Chapter 21) into list(s) of fvlist;
    • the hypercolumn(s) that are solist(s) (Chapter 39) into list(s) of solist.
  • aggregates, according to the grouping level specified in the parameter by,
    • the regular column(s) by simply taking their unique-value, as the elements in each column must be all.equal within each grouping of by;
    • the hypercolumn(s) that are vectorlist(s) (Chapter 41) using the aggregation method provided in the parameter fun (Section 41.4).
  • returns a hyperframe.

When the primary input is a grouped hyper data frame (Chapter 25, e.g., in Section 3.4), the aggregation may be specified at either one of the nested grouping levels (Chapter 46) \(g_1,\cdots,g_{m-1}\). Aggregation at the lowest grouping level \(g_m\) is ignored, i.e., no aggregation to be performed.

26.7 Aggregate Marks-Statistics from ppp-hypercolumn

The S3 method aggregate_marks.hyperframe() (Section 36.7, Table 36.7)

  • aggregates the marks of one-and-only-one (Section 26.13) ppp-hypercolumn in the input hyper data frame, using the S3 method aggregate_marks.ppplist() (Section 37.4);
  • appends the returned numeric-vectorlist to the input as a new hypercolumn named 'markstats'.

Listing 26.10 shows the hyper data frame flu (Section 10.10) has a ppp-hypercolumn with one multi-type mark.

Listing 26.10: Review: hypercolumn flu$pattern
spatstat.data::flu$pattern[[1L]] |>
  spatstat.geom::marks.ppp() |>
  table()
# 
#  M2  M1 
# 117 354

Listing 26.11 aggregates the relative frequencies of the sole multi-type mark in the ppp-hypercolumn flu$pattern.

Listing 26.11: Example: function aggregate_marks.hyperframe(), for relative frequencies
flu_mfreq = spatstat.data::flu |> 
  aggregate_marks(FUN = \(z) table(z)/length(z))
flu_mfreq
# Hyperframe:
#                pattern virustype stain frameid markstats
# wt M2-M1 13      (ppp)        wt M2-M1      13 (numeric)
# wt M2-M1 22      (ppp)        wt M2-M1      22 (numeric)
# wt M2-M1 27      (ppp)        wt M2-M1      27 (numeric)
# ✂️ --- output truncated --- ✂️

Listing 26.12 shows the aggregated relative frequencies in the returned hypercolumn flu_mfreq$markstats.

Listing 26.12: Example: inside numeric-hypercolumn flu_mfreq$markstats (Listing 26.11)
flu_mfreq$markstats
# wt M2-M1 13:
#        M2        M1 
# 0.2484076 0.7515924 
# 
# wt M2-M1 22:
#        M2        M1 
# 0.2995392 0.7004608 
# ✂️ --- output truncated --- ✂️

As explained in Section 37.4, the S3 method t.vectorlist() (Section 41.3) is the fastest way to extract a “slice” from the numeric-hypercolumn, e.g., flu_mfreq$markstats.

Listing 26.13: Advanced: function t.vectorlist() (Listing 26.11)
flu_mfreq$markstats[1:4] |>
  t.vectorlist()
# A 'vectorlist' of 2 vectors 
# Name(s): M2, M1 
# Storage Mode: numeric 
# Individual Vector Length: 4

Unfortunately, package spatstat.data (v3.1.9) does not have a hyper data frame with (any) ppp-hypercolumn of

  • 'dataframe' mark-format, to showcase the use of parameter by in the S3 method aggregate_marks.hyperframe().
  • 'vector' mark-format and numeric marks, to showcase the aggregation by sample mean and standard deviation.

26.8 Create groupedHyperframe

The S3 method as.groupedHyperframe.hyperframe() (Section 18.1, Table 18.2) converts a hyper data frame into a grouped hyper data frame by inspecting and adding a (nested) grouping structure to the input.

Listing 26.14 adds a nested grouping structure ~id/brick to the hyper data frame osteo (Section 10.18).

Listing 26.14: Example: function as.groupedHyperframe.hyperframe()
spatstat.data::osteo |> 
  as.groupedHyperframe(group = ~ id/brick)
# Grouped Hyperframe: ~id/brick
# 
# 40 brick nested in
# 4 id
# 
#         id shortid brick   pts depth
# 1   c77za4       4     1 (pp3)    45
# 2   c77za4       4     2 (pp3)    60
# 3   c77za4       4     3 (pp3)    55
# 4   c77za4       4     4 (pp3)    60
# ✂️ --- output truncated --- ✂️

26.9 Superimpose

Listing 26.15 summarizes the S3 methods of the generic function spatstat.geom::superimpose() (v3.6.1.16) in the spatstat.* family of packages,

Listing 26.15: S3 methods spatstat.*::superimpose.*
Code
suppressPackageStartupMessages(library(spatstat))
.S3methods(generic = 'superimpose', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = grepl(pattern = '^spatstat\\.', x = from))
#                      visible            from     generic  isS4
# superimpose.default     TRUE   spatstat.geom superimpose FALSE
# superimpose.lpp         TRUE spatstat.linnet superimpose FALSE
# superimpose.ppp         TRUE   spatstat.geom superimpose FALSE
# superimpose.ppplist     TRUE   spatstat.geom superimpose FALSE
# superimpose.psp         TRUE   spatstat.geom superimpose FALSE
# superimpose.splitppp    TRUE   spatstat.geom superimpose FALSE

The S3 method superimpose.hyperframe() superimposes multiple hyper data frames if-and-only-if they have identical

The S3 method superimpose.hyperframe() performs a by-element superimpose of all point-pattern hypercolumns of all input hyper data frames.

Listing 26.16 shows that the hypercolumn fluM$pattern (Listing 26.3) contains 8 point-patterns, each of them has 200-500 points.

Listing 26.16: Review: number of points per point-pattern in fluM$pattern (Listing 26.3)
Code
fluM$pattern |>
  sapply(FUN = spatstat.geom::npoints.ppp)
# wt M2-M1 13 wt M2-M1 22 wt M2-M1 27 wt M2-M1 43 wt M2-M1 49 wt M2-M1 65 wt M2-M1 71 wt M2-M1 84 
#         471         217         214         406         417         318         265         509
Listing 26.17: Review: number of M1 and/or M2 points per point-pattern in fluM$pattern (Listing 26.3)
Code
fluM$pattern |>
  sapply(FUN = \(i) {
    i |> 
      spatstat.geom::marks.ppp() |> 
      table()
  }) |>
  addmargins()
#     wt M2-M1 13 wt M2-M1 22 wt M2-M1 27 wt M2-M1 43 wt M2-M1 49 wt M2-M1 65 wt M2-M1 71 wt M2-M1 84  Sum
# M2          117          65          71         241         150         116          57         104  921
# M1          354         152         143         165         267         202         208         405 1896
# Sum         471         217         214         406         417         318         265         509 2817

Listing 26.18 creates a hyper data frame fluM1 which consists of the same columns as fluM, but a ppp-hypercolumn pattern with M1 marks only; and another hyper data frame fluM2 which consists of the M2 marks only. Note that as of package spatstat.geom v3.6.1.16, the tedious code in Listing 26.18 is the only way to avoid using the row names of hyper data frame as the element-names of the hypercolumns. In other words, function unclass() avoids invoking the S3 method spatstat.geom::`$.hyperframe`. The S3 method spatstat.geom::`$<-.hyperframe` is fine in this application.

Listing 26.18: Data: two hyper data frames fluM1 and fluM2
fluM1 = fluM2 = fluM
fluM1$pattern = unclass(fluM)$hypercolumns$pattern |> 
  spatstat.geom::solapply(FUN = spatstat.geom::subset.ppp, subset = (marks == 'M1'))
fluM2$pattern = unclass(fluM)$hypercolumns$pattern |> 
  spatstat.geom::solapply(FUN = spatstat.geom::subset.ppp, subset = (marks == 'M2'))
Listing 26.19: Review: number of M1 points per point-pattern in fluM1$pattern (Listing 26.18)
Code
fluM1$pattern |>
  sapply(FUN = spatstat.geom::npoints.ppp)
# wt M2-M1 13 wt M2-M1 22 wt M2-M1 27 wt M2-M1 43 wt M2-M1 49 wt M2-M1 65 wt M2-M1 71 wt M2-M1 84 
#         354         152         143         165         267         202         208         405
Listing 26.20: Review: number of M2 points per point-pattern in fluM2$pattern (Listing 26.18)
Code
fluM2$pattern |>
  sapply(FUN = spatstat.geom::npoints.ppp)
# wt M2-M1 13 wt M2-M1 22 wt M2-M1 27 wt M2-M1 43 wt M2-M1 49 wt M2-M1 65 wt M2-M1 71 wt M2-M1 84 
#         117          65          71         241         150         116          57         104

Listing 26.21 recreates the hyper data frame fluM (Listing 26.3) by superimposing the hyper data frames fluM2 and fluM1 (Listing 26.18). Note that the order of fluM2-then-fluM1 matters, because the points are arranged in M2-then-M1 in the original hypercolumn fluM$pattern.

Listing 26.21: Example: function superimpose.hyperframe() (Listing 26.3, Listing 26.18)
superimpose.hyperframe(fluM2, fluM1) |>
  identical(y = fluM) |>
  stopifnot()

Note that the S3 method spatstat.geom::superimpose.ppplist() (v3.6.1.16) superimposes all point-patterns from all input point-pattern-lists (Listing 26.22).

Listing 26.22: Review: spatstat.geom::superimpose.ppplist() not what we need (Listing 26.18)
Code
list(
  'all superimposed' = spatstat.geom::superimpose.ppplist(
    unclass(fluM2)$hypercolumns$pattern, 
    unclass(fluM1)$hypercolumns$pattern
  ) |>
    spatstat.geom::npoints.ppp(),
  'all M2' = fluM2$pattern |> 
    vapply(FUN = spatstat.geom::npoints.ppp, FUN.VALUE = NA_integer_) |>
    sum(),
  'all M1' = fluM1$pattern |> 
    vapply(FUN = spatstat.geom::npoints.ppp, FUN.VALUE = NA_integer_) |>
    sum()
)
# $`all superimposed`
# [1] 2817
# 
# $`all M2`
# [1] 921
# 
# $`all M1`
# [1] 1896

26.10 Attributes per Element

The S3 generic function attr_.hyperframe() (Section 15.4, Table 15.3)

  • extracts the specified attribute per element, per hypercolumn of a hyper data frame;
  • appends these attributes, if exist, to the input hyper data frame as columns or hypercolumns, named in the fashion of $<hypercolumn>.<which>.

Examples of the S3 method attr_.hyperframe() are Listing 26.23.

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

The S3 method .rmax.hyperframe() (Section 36.10, Table 36.11) obtains the default \(r_\text{max}\) of the one-or-more ppp-hypercolumn(s) (Section 37.6) before the (potentially) very slow batch processes.

Example: function .rmax.hyperframe() for Emark_(), Vmark_(), markcorr_(), markvario_() on numeric- and multi-type mark
s |> .rmax(fun = 'K')
Example: function .rmax.hyperframe() for Kcross_() on multi-type mark
s |> .rmax(fun = 'K', i = 'CK+.CD8-', j = 'CK-.CD8+')
s |> .rmax(fun = 'K', i = 'CK-.CD8+', j = 'CK+.CD8-')
Example: function .rmax.hyperframe() for Gcross_() on multi-type mark
s |> .rmax(fun = 'G', i = 'CK+.CD8-', j = 'CK-.CD8+')
s |> .rmax(fun = 'G', i = 'CK-.CD8+', j = 'CK+.CD8-')
Example: function .rmax.hyperframe() for Jcross_() on multi-type mark
s |> .rmax(fun = 'J', i = 'CK+.CD8-', j = 'CK-.CD8+')
s |> .rmax(fun = 'J', i = 'CK-.CD8+', j = 'CK+.CD8-')

26.12 Random Re-Labelling Envelope Residual & Test

The S3 method rlabelRes.hyperframe() (Section 36.13, Table 36.18)

  1. applies the S3 method rlabelRes.ppplist() (Section 37.8) on the one-and-only-one ppp-hypercolumn of the input hyper data frame;
  2. appends a 'curve_set' (Chapter 17) hypercolumn $.rlabelRes to the input hyper data frame.

The S3 method global_envelope_test_.hyperframe() (Section 15.3, Table 15.2)

  1. applies the S3 method global_envelope_test_.anylist() (Section 15.3) to the 'curve_set' (Chapter 17) hypercolumn(s) of the input hyper data frame;
  2. appends the 'global_envelope' (Chapter 23) hypercolumn(s) to the input hyper data frame, named in the fashion of $<curve_set>.GET.

Listing 26.23 performs the random re-labelling envelope residual and test on the ppp-hypercolumn fluM$pattern (Listing 26.3), and creates a hyper data frame with

  • a 'curve_set' hypercolumn $.rlabelRes;
  • a 'global_envelope' hypercolumn $.rlabelRes.GET;
  • a numeric column $.rlabelRes.GET.p, the \(p\)-values per element of the hypercolumn $.rlabelRes.GET.
Listing 26.23: Example: functions rlabelRes.hyperframe(), global_envelope_test_.hyperframe() and attr_.hyperframe() (Section 26.10) on fluM (Listing 26.3)
fluM |>
  rlabelRes(fun = spatstat.explore::Gcross) |>
  global_envelope_test_() |>
  attr_(which = 'p', exact = TRUE)
# Hyperframe:
#             pattern frameid  .rlabelRes    .rlabelRes.GET .rlabelRes.GET.p
# wt M2-M1 13   (ppp)      13 (curve_set) (global_envelope)             0.01
# wt M2-M1 22   (ppp)      22 (curve_set) (global_envelope)             0.04
# wt M2-M1 27   (ppp)      27 (curve_set) (global_envelope)             0.02
# wt M2-M1 43   (ppp)      43 (curve_set) (global_envelope)             0.01
# wt M2-M1 49   (ppp)      49 (curve_set) (global_envelope)             0.04
# wt M2-M1 65   (ppp)      65 (curve_set) (global_envelope)             0.01
# wt M2-M1 71   (ppp)      71 (curve_set) (global_envelope)             0.04
# wt M2-M1 84   (ppp)      84 (curve_set) (global_envelope)             0.01

26.13 Batch Process on Eligible Marks

The S3 methods Emark_.hyperframe(), Vmark_.hyperframe(), etc., in Table 26.1 are user-friendly wrappers of the low-level utility function op_hyperframe(), for batch operation on hyper data frame (Section 3.2). Function op_hyperframe()

  1. performs the batch operation on the one-and-only-one ppp-hypercolumn (Section 37.9) of the input hyper data frame. The batch operation is not designed to handle a hyper data frame containing multiple ppp-hypercolumns, e.g., cetaceans (Section 10.7). Supporting such functionality would require resolving potential name clashes in the marks across multiple ppp-hypercolumns.
  2. column-binds the two-level hierarchical list returned from the previous step to the input hyper data frame.

Listing 26.24 calls the S3 method Gcross_.hyperframe() to

  1. create an fv-hypercolumn $m.G by applying the S3 method Gcross_.ppplist() (Section 37.9) to the ppp-hypercolumn fluM$pattern (Listing 26.3);
  2. return a hyper data frame fluG.
Listing 26.24: Data: a hyper data frame fluG (Listing 26.3)
fluG = fluM |>
  Gcross_(i = 'M1', j = 'M2', r = 0:300)
fluG
# Hyperframe:
#             pattern frameid  m.G
# wt M2-M1 13   (ppp)      13 (fv)
# wt M2-M1 22   (ppp)      22 (fv)
# wt M2-M1 27   (ppp)      27 (fv)
# ✂️ --- output truncated --- ✂️

26.14 Function Value from fv-Hypercolumns

The S3 method keyval.hyperframe() (Section 20.2, Table 20.3)

  • applies the S3 method keyval.fvlist() (Section 21.4) across all fv-hypercolumns of the input hyper data frame;
  • appends the numeric-hypercolumn(s) $<mark>.<fv>.<selected_value> to the input hyper data frame;
  • returns a hyper data frame.

Listing 26.25 works on the hyper data frame fluG (Listing 26.24) to

  1. create a numeric-hypercolumn $m.G.y of the recommended function values of the fv-hypercolumn fluG$m.G in the returned hyper data frame, using the S3 method keyval.hyperframe();
  2. create a numeric-hypercolumn $m.G.theo of the theoretical function values of the fv-hypercolumn fluG$m.G in the returned hyper data frame, using the S3 method keyval.hyperframe(., key = 'theo').
Listing 26.25: Example: function keyval.hyperframe() (Listing 26.24)
fluG |>
  keyval() |>
  keyval(key = 'theo')
# Hyperframe:
#             pattern frameid  m.G     m.G.y  m.G.theo
# wt M2-M1 13   (ppp)      13 (fv) (numeric) (numeric)
# wt M2-M1 22   (ppp)      22 (fv) (numeric) (numeric)
# wt M2-M1 27   (ppp)      27 (fv) (numeric) (numeric)
# ✂️ --- output truncated --- ✂️

26.15 Cumulative Average Vertical Height of Trapzoidal Integration of fv-Hypercolumn

The S3 method cumvtrapz.hyperframe() (Section 11.1, Table 11.1)

  • runs the workhorse function cumvtrapz.fvlist() (Section 21.6) across all fv-hypercolumns of the input hyper data frame;
  • appends additional numeric-hypercolumns $<mark>.<fv>.cumvtrapz to the input hyper data frame;
  • returns a hyper data frame.

Listing 26.26 applies the S3 method cumvtrapz.hyperframe() to the hyper data frame fluG (Listing 26.24) and creates a numeric-hypercolumn $m.G.cumvtrapz from the fv-hypercolumn fluG$m.G in the returned hyper data frame fluG_vt.

Listing 26.26: Example: function cumvtrapz.hyperframe() (Listing 26.24)
fluG_vt = fluG |>
  cumvtrapz()
fluG_vt
# Hyperframe:
#             pattern frameid  m.G m.G.cumvtrapz
# wt M2-M1 13   (ppp)      13 (fv)     (numeric)
# wt M2-M1 22   (ppp)      22 (fv)     (numeric)
# wt M2-M1 27   (ppp)      27 (fv)     (numeric)
# ✂️ --- output truncated --- ✂️

The S3 method t.vectorlist() (Section 41.3) is the fastest way to extract a “slice” from a numeric-hypercolumn, e.g., fluG_vt$m.G.cumvtrapz (Listing 26.26), which is a 'vectorlist' (Chapter 41) although not supported as a hypercolumn in hyper data frame as of package spatstat.geom (v3.6.1.16). A “slice” of the hypercolumn fluG_vt$m.G.cumvtrapz at the 50th index of the \(r\)-vector, i.e., \(r=50\), may be extracted by calling the S3 method spatstat.geom::with.hyperframe() (Listing 26.28), but the S3 method t.vectorlist() (Listing 26.27) is much faster.

Listing 26.27: Advanced: function t.vectorlist() (Listing 26.26)
tG = fluG_vt$m.G.cumvtrapz |>
  t.vectorlist()
Listing 26.28: Review: function spatstat.geom::with.hyperframe() (Listing 26.26, Listing 26.27)
Code
fluG_vt |>
  spatstat.geom::with.hyperframe(expr = {
    m.G.cumvtrapz['50']
  }) |>
  identical(y = tG[[50L]]) |>
  stopifnot()
fluG_vt |>
  spatstat.geom::with.hyperframe(expr = {
    m.G.cumvtrapz[50L]
  }) |>
  identical(y = tG[[50L]]) |>
  stopifnot()

26.16 Handling Illegal Recommended-Function-Value

The S3 generic functions .illegal2theo() and .disrecommend2theo() have been introduced in Section 20.5.1 (Table 20.5, Table 20.6). The S3 methods .illegal2theo.hyperframe() and .disrecommend2theo.hyperframe()

  • apply the S3 methods .illegal2theo.fvlist() and .disrecommend2theo.fvlist() (Section 21.5), respectively, to all fv-hypercolumns of the input hyper data frame;
  • overwrite the fv-hypercolumns in the input hyper data frame;
  • return a hyper data frame.

Listing 26.29 applies the S3 method .disrecommend2theo.hyperframe() on the hyper data frame fluG (Listing 26.24) and overwrites the fv-hypercolumn $m.G in the returned hyper data frame.

Listing 26.29: Example: function .disrecommend2theo.hyperframe() (Listing 26.24)
fluG |>
  .disrecommend2theo()
# Hyperframe:
#             pattern frameid  m.G
# wt M2-M1 13   (ppp)      13 (fv)
# wt M2-M1 22   (ppp)      22 (fv)
# wt M2-M1 27   (ppp)      27 (fv)
# ✂️ --- output truncated --- ✂️

26.17 \(k\)-Means Clustering

Function kmeans.hyperframe()

  • 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.
  • performs \(k\)-means clustering on the one-and-only-one (Section 26.13) ppp-hypercolumn via kmeans.ppplist() (Section 37.7).
  • returns an object of class 'hyperframekm', which inherits from 'hyperframe'.

Package groupedHyperframe (v0.3.2.20251225) implements the following S3 methods to the class 'hyperframekm' (Table 26.3),

Table 26.3: S3 methods groupedHyperframe::*.hyperframekm (v0.3.2.20251225)
visible from generic isS4
split.hyperframekm TRUE groupedHyperframe base::split FALSE

26.17.1 Examples

Listing 26.30 performs \(k\)-means clustering of the ppp-hypercolumn fluM$pattern in the hyper data frame fluM (Listing 26.3).

Listing 26.30: Example: function kmeans.hyperframe() (Listing 26.3)
set.seed(13); flu_k = fluM |> 
  kmeans.hyperframe(formula = ~ x + y, centers = 3L)
flu_k
# Hyperframe:
#             pattern frameid
# wt M2-M1 13   (ppp)      13
# wt M2-M1 22   (ppp)      22
# wt M2-M1 27   (ppp)      27
# wt M2-M1 43   (ppp)      43
# wt M2-M1 49   (ppp)      49
# wt M2-M1 65   (ppp)      65
# wt M2-M1 71   (ppp)      71
# wt M2-M1 84   (ppp)      84
Listing 26.31: Example: A hyperframekm flu_k (Listing 26.30)
flu_k |>
  class()
# [1] "hyperframekm" "hyperframe"   "list"
Listing 26.32: Example: hypercolumn flu_k$pattern (Listing 26.30)
flu_k$pattern |>
  lapply(FUN = class)
# $`wt M2-M1 13`
# [1] "pppkm" "ppp"  
# 
# $`wt M2-M1 22`
# [1] "pppkm" "ppp"  
# 
# $`wt M2-M1 27`
# [1] "pppkm" "ppp"  
# 
# ✂️ --- output truncated --- ✂️

26.17.2 Split by \(k\)-Means Clustering

The S3 method split.hyperframekm() splits a hyperframekm by the \(k\)-means clustering indices of the one-and-only-one (Section 26.13) ppp-hypercolumn. The returned object is a grouped hyper data frame with grouping structure

  • ~.id/.cluster, if the input is a hyper data frame
  • ~ <existing/grouping/structure>/.cluster, if the input is a grouped hyper data frame. Note that the grouping level .id is believed to be equivalent to the lowest level of existing grouping structure.

Listing 26.33 splits the hyper data frame fluM (Listing 26.3) by the \(k\)-means clustering of the ppp-hypercolumn fluM$pattern.

Listing 26.33: Example: function split.hyperframekm() (Listing 26.3)
set.seed(13); fluM |> 
  kmeans.hyperframe(formula = ~ x + y, centers = 3L) |> 
  split()
# Grouped Hyperframe: ~.id/.cluster
# 
# 24 .cluster nested in
# 8 .id
# 
#    pattern .id .cluster frameid
# 1    (ppp)   1        1      13
# 2    (ppp)   1        2      13
# 3    (ppp)   1        3      13
# 4    (ppp)   2        1      22
# 5    (ppp)   2        2      22
# 6    (ppp)   2        3      22
# ✂️ --- output truncated --- ✂️