17  hyperframe

The examples in Chapter 17 require that the search path contains the following namespaces,

library(groupedHyperframe)

Function spatstat.geom::hyperframe() creates a hyper data frame, i.e., an R object of S3 class 'hyperframe'. In addition to the existing S3 method dispatches spatstat.geom::*.hyperframe (v3.6.0.3, Listing 17.1),

Listing 17.1: Existing S3 method dispatches spatstat.geom::*.hyperframe
Code
suppressPackageStartupMessages(library(spatstat.geom))
methods(class = 'hyperframe', all.names = TRUE) |> 
  attr(which = 'info', exact = TRUE) |>
  subset.data.frame(subset = from == 'spatstat.geom')
#                          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

Package groupedHyperframe (v0.3.0.20251020) implements more S3 method dispatches to the class 'hyperframe' (Listing 17.2, Table 17.1),

Listing 17.2: Table: S3 method dispatches groupedHyperframe::*.hyperframe
Code
suppressPackageStartupMessages(library(spatstat.geom)) # must! for S3 generic function `spatstat.geom::superimpose`
methods2kable(class = 'hyperframe', package = 'groupedHyperframe', all.names = TRUE)
Table 17.1: S3 method dispatches groupedHyperframe::*.hyperframe (v0.3.0.20251020)
visible from generic isS4
.disrecommend2theo.hyperframe TRUE groupedHyperframe groupedHyperframe::.disrecommend2theo FALSE
.illegal2theo.hyperframe TRUE groupedHyperframe groupedHyperframe::.illegal2theo FALSE
.kmeans.hyperframe TRUE groupedHyperframe groupedHyperframe::.kmeans FALSE
.rmax.hyperframe TRUE groupedHyperframe groupedHyperframe::.rmax FALSE
aggregate_marks.hyperframe TRUE groupedHyperframe groupedHyperframe::aggregate_marks FALSE
aggregate.hyperframe TRUE groupedHyperframe stats::aggregate FALSE
as.groupedHyperframe.hyperframe TRUE groupedHyperframe groupedHyperframe::as.groupedHyperframe FALSE
Emark_.hyperframe TRUE groupedHyperframe groupedHyperframe::Emark_ FALSE
Gcross_.hyperframe TRUE groupedHyperframe groupedHyperframe::Gcross_ FALSE
Jcross_.hyperframe TRUE groupedHyperframe groupedHyperframe::Jcross_ FALSE
Kcross_.hyperframe TRUE groupedHyperframe groupedHyperframe::Kcross_ FALSE
kerndens.hyperframe TRUE groupedHyperframe groupedHyperframe::kerndens FALSE
Kmark_.hyperframe TRUE groupedHyperframe groupedHyperframe::Kmark_ FALSE
Lcross_.hyperframe TRUE groupedHyperframe groupedHyperframe::Lcross_ FALSE
length.hyperframe TRUE groupedHyperframe base::length FALSE
markconnect_.hyperframe TRUE groupedHyperframe groupedHyperframe::markconnect_ FALSE
markcorr_.hyperframe TRUE groupedHyperframe groupedHyperframe::markcorr_ FALSE
markvario_.hyperframe TRUE groupedHyperframe groupedHyperframe::markvario_ FALSE
nncross_.hyperframe TRUE groupedHyperframe groupedHyperframe::nncross_ FALSE
quantile.hyperframe TRUE groupedHyperframe stats::quantile FALSE
superimpose.hyperframe TRUE groupedHyperframe spatstat.geom::superimpose FALSE
Vmark_.hyperframe TRUE groupedHyperframe groupedHyperframe::Vmark_ FALSE
Table 17.2: S3 method dispatches currently not planned for class 'hyperframe'
Table 17.2: S3 method dispatches currently not planned for class 'hyperframe'
Not Planned Explained in
as.environment.hyperframe() Section 30.1
merge.hyperframe() Section 30.2

17.1 Plot

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

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

Listing 17.3 deems the multi-type ppp-hypercolumn flu$pattern (Section 8.10) to be plot-able, and plots them.

Listing 17.3: Review: spatstat.geom::plot.hyperframe(); plot ppp-hypercolumn flu$pattern
spatstat.data::flu[1:2, ] |>
  spatstat.geom::plot.hyperframe()

17.2 Length

The S3 method dispatch length.hyperframe() finds the number of columns and/or hypercolumns of a hyperframe. The authors define this S3 method dispatch to reproduce the behavior of the .Primitive S3 generic function base::length() when dispatched to objects of class 'data.frame'.

Listing 17.4 reveals that the data.frame Formaldehyde from package datasets shipped with R version 4.5.1 (2025-06-13) has 2 columns;

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

Listing 17.5 reveals that the hyper data frame demohyper (Section 8.8) has 3 (hyper)columns.

Listing 17.5: Example: function length.hyperframe()
spatstat.data::demohyper |>
  length()
# [1] 3

17.3 Kernel Density

The S3 method dispatch kerndens.hyperframe() finds the kernel densitys

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

17.4 Quantile

The S3 method dispatch quantile.hyperframe() finds the quantiles

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

17.5 Aggregation

The S3 method dispatch aggregate.hyperframe()

  • splits (Section 11.3), according to the grouping level specified in the parameter by,
    • the hypercolumn(s) that are ppplist(s) (Chapter 24) into list(s) of ppplist;
    • the hypercolumn(s) that are imlist(s) (Chapter 20) into list(s) of imlist;
    • the hypercolumn(s) that are fvlist(s) (Chapter 14) into list(s) of fvlist;
    • the hypercolumn(s) that are solist(s) (Chapter 25) 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 27) using the aggregation method provided in the parameter fun (Section 27.4).
  • returns a hyperframe.

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

17.6 Aggregation of marks from ppp-hypercolumn

The S3 generic function aggregate_marks() has been introduced in Section 23.8. The S3 method dispatch aggregate_marks.hyperframe()

  • aggregates the marks of one-and-only-one (Section 17.13) ppp-hypercolumn in the input (Section 24.4);
  • appends the returned numeric-vectorlist to the input as a new hypercolumn named 'markstats'.

The authors use the hyper data frame flu (Section 8.10) to illustrate the aggregation of relative frequency of the sole multitype-mark in the ppp-hypercolumn $pattern.

Review: flu$pattern is a ppp-hypercolumn with one multitype-mark
spatstat.data::flu$pattern[[1L]] |>
  spatstat.geom::marks.ppp() |>
  table()
# 
#  M2  M1 
# 117 354
Example: function aggregate_marks.hyperframe(), for relative frequency
flu_mfreq = spatstat.data::flu |> 
  aggregate_marks(FUN = \(z) table(z)/length(z))
flu_mfreq |>
  head(n = 3L)
# 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)
flu_mfreq$markstats
# wt M2-M1 13:
#        M2        M1 
# 0.2484076 0.7515924 
# 
# wt M2-M1 22:
#        M2        M1 
# 0.2995392 0.7004608 
# 
# wt M2-M1 27:
#        M2        M1 
# 0.3317757 0.6682243 
# 
# wt M2-M1 43:
#        M2        M1 
# 0.5935961 0.4064039 
# 
# wt M2-M1 49:
#        M2        M1 
# 0.3597122 0.6402878 
# 
# wt M2-M1 65:
#        M2        M1 
# 0.3647799 0.6352201 
# 
# wt M2-M1 71:
#        M2        M1 
# 0.2150943 0.7849057 
# 
# wt M2-M1 84:
#        M2        M1 
# 0.2043222 0.7956778 
# 
# wt M2-HA 3:
#        M2        HA 
# 0.1235955 0.8764045 
# 
# wt M2-HA 4:
#         M2         HA 
# 0.08552632 0.91447368 
# 
# wt M2-HA 5:
#        M2        HA 
# 0.1532067 0.8467933 
# 
# wt M2-HA 17:
#         M2         HA 
# 0.07642031 0.92357969 
# 
# wt M2-HA 54:
#        M2        HA 
# 0.0488746 0.9511254 
# 
# wt M2-HA 74:
#         M2         HA 
# 0.07753623 0.92246377 
# 
# wt M2-HA 78:
#         M2         HA 
# 0.08067093 0.91932907 
# 
# wt M2-HA 82:
#         M2         HA 
# 0.08860759 0.91139241 
# 
# wt M2-HA 85:
#         M2         HA 
# 0.08832808 0.91167192 
# 
# wt M2-HA 100:
#         M2         HA 
# 0.08317699 0.91682301 
# 
# wt M2-HA 110:
#        M2        HA 
# 0.1409456 0.8590544 
# 
# mut1 M2-M1 11:
#        M2        M1 
# 0.7816901 0.2183099 
# 
# mut1 M2-M1 13:
#        M2        M1 
# 0.8134328 0.1865672 
# 
# mut1 M2-M1 15:
#        M2        M1 
# 0.9205298 0.0794702 
# 
# mut1 M2-M1 17:
#         M2         M1 
# 0.93874539 0.06125461 
# 
# mut1 M2-M1 28:
#         M2         M1 
# 0.93222506 0.06777494 
# 
# mut1 M2-M1 29:
#        M2        M1 
# 0.7755474 0.2244526 
# 
# mut1 M2-M1 33:
#        M2        M1 
# 0.7953668 0.2046332 
# 
# mut1 M2-M1 38:
#        M2        M1 
# 0.3823529 0.6176471 
# 
# mut1 M2-M1 41:
#        M2        M1 
# 0.8075314 0.1924686 
# 
# mut1 M2-M1 44:
#        M2        M1 
# 0.7272727 0.2727273 
# 
# mut1 M2-M1 59:
#        M2        M1 
# 0.8545994 0.1454006 
# 
# mut1 M2-HA 8:
#        M2        HA 
# 0.4059829 0.5940171 
# 
# mut1 M2-HA 14:
#        M2        HA 
# 0.2336343 0.7663657 
# 
# mut1 M2-HA 23:
#        M2        HA 
# 0.3895582 0.6104418 
# 
# mut1 M2-HA 42:
#        M2        HA 
# 0.4547619 0.5452381 
# 
# mut1 M2-HA 51:
#       M2       HA 
# 0.532097 0.467903 
# 
# mut1 M2-HA 59:
#        M2        HA 
# 0.3274232 0.6725768 
# 
# mut1 M2-HA 73:
#        M2        HA 
# 0.3585799 0.6414201 
# 
# mut1 M2-HA 79:
#       M2       HA 
# 0.477195 0.522805 
# 
# mut1 M2-HA 86:
#        M2        HA 
# 0.2168979 0.7831021 
# 
# mut1 M2-HA 104:
#        M2        HA 
# 0.2893726 0.7106274 
# 
# mut1 M2-HA 147:
#        M2        HA 
# 0.2068966 0.7931034

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

Advanced: function t.vectorlist()
flu_mfreq$markstats[1:4] |>
  t.vectorlist()
# M2:
# wt M2-M1 13 wt M2-M1 22 wt M2-M1 27 wt M2-M1 43 
#   0.2484076   0.2995392   0.3317757   0.5935961 
# 
# M1:
# wt M2-M1 13 wt M2-M1 22 wt M2-M1 27 wt M2-M1 43 
#   0.7515924   0.7004608   0.6682243   0.4064039

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

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

17.7 Convert to groupedHyperframe

The S3 generic function as.groupedHyperframe() are introduced in Section 12.1. The S3 method dispatch as.groupedHyperframe.hyperframe() converts a hyperframe into a groupedHyperframe by inspecting and adding a (nested) grouping structure to the input.

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

Listing 17.6: Example: function as.groupedHyperframe.hyperframe()
spatstat.data::osteo |> 
  as.groupedHyperframe(group = ~ id/brick)
# Grouped Hyperframe: ~id/brick
# 
# 40 brick nested in
# 4 id
# 
# Preview of first 10 (or less) rows:
# 
#        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
# 5  c77za4       4     5 (pp3)    85
# 6  c77za4       4     6 (pp3)    90
# 7  c77za4       4     7 (pp3)    95
# 8  c77za4       4     8 (pp3)    65
# 9  c77za4       4     9 (pp3)   100
# 10 c77za4       4    10 (pp3)   100

17.8 Superimpose

The S3 method dispatch superimpose.hyperframe() superimposes multiple hyperframes if-and-only-if they have identical

  • dimensions, i.e., spatstat.geom::dim.hyperframe()
  • columns, i.e., unclass(.)$df
  • names and class of the hypercolumns, i.e., unclass(.)$hypercolumns

The authors use the hyper data frame fluM (Section 8.10) to illustrate the superimpose of hyperframes.

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

The hyper data frame fluM contains 8 subjects, each of them has a ppp.object with 200-500 points.

Review: number of points per ppp.object in hypercolumn fluM$pattern
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
Review: number of M1 and/or M2 points per ppp.object in hypercolumn fluM$pattern
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

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

Data: two hyperframe objects 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'))
Review: number of M1 points per ppp.object in hypercolumn fluM1$pattern
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
Review: number of M2 points per ppp.object in hypercolumn fluM2$pattern
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

The S3 method dispatch superimpose.hyperframe() recreates the hyper data frame fluM by combining the hyper data frames fluM2 and fluM1. Note that the order of fluM2-then-fluM1 matters, because the points are arranged in M2-then-M1 in the original hypercolumn fluM$pattern.

Example: function superimpose.hyperframe()
fluS = superimpose.hyperframe(fluM2, fluM1)
stopifnot(identical(fluS, fluM))

The S3 method dispatch spatstat.geom::superimpose.ppplist() (v3.6.0.3) superimposes all ppp.objects from all input ppplists, instead of performing a by-element superimpose of all input ppplists as intended for the S3 method dispatch superimpose.hyperframe().

Review: spatstat.geom::superimpose.ppplist() (Baddeley, Rubak, and Turner 2015) not what we need
spatstat.geom::superimpose.ppplist(
  unclass(fluM2)$hypercolumns$pattern, 
  unclass(fluM1)$hypercolumns$pattern
)
# Marked planar point pattern: 2817 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm
fluM2$pattern |> 
  vapply(FUN = spatstat.geom::npoints.ppp, FUN.VALUE = NA_integer_) |>
  sum()
# [1] 921
fluM1$pattern |> 
  vapply(FUN = spatstat.geom::npoints.ppp, FUN.VALUE = NA_integer_) |>
  sum()
# [1] 1896

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

The S3 generic function .rmax() has been introduced in Section 23.11. The S3 method dispatch .rmax.hyperframe() obtains the default \(r_\text{max}\) of the one-or-more ppp-hypercolumn(s) (Section 24.5) before the (potentially) very slow batch processes.

Example: function .rmax.hyperframe() for Emark_(), Vmark_(), markcorr_(), markvario_() on numeric- and multitype-mark
s |> .rmax(fun = 'K')
Example: function .rmax.hyperframe() for Kcross_() on multitype-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 multitype-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 multitype-mark
s |> .rmax(fun = 'J', i = 'CK+.CD8-', j = 'CK-.CD8+')
s |> .rmax(fun = 'J', i = 'CK-.CD8+', j = 'CK+.CD8-')

17.10 Summarize fv-Hypercolumns

Function summary_fv()

  • runs the workhorse function summary.fvlist() (Section 14.3) across all fv-hypercolumns of the input hyperframe and/or groupedHyperframe (Chapter 16).
    • When a user-specified \(r\)-vector is provided to a batch process (Section 3.2) on all ppp.objects in the ppp-hypercolumns, inevitably some of the fv-returns may contain exceptional/illegal recommended-function-values (Section 13.3). In this case, the summary is truncated at the minimum legal \(r_\text{max}\) (attr(,'rmax'), Section 14.2) of each fv-hypercolumn.
    • Alternatively, user may specify an \(r_\text{max}\) for truncation using the argument rmax. If the user-specified \(r_\text{max}\) is greater than the minimum legal \(r_\text{max}\) (attr(,'rmax'), Section 14.2) of some fv-hypercolumns, the user’s \(r_\text{max}\) will be ignored (Section 14.3) for those fv-hypercolumns.
  • appends additional numeric-hypercolumns to the input,
    • <mark>.<fv>.y, the recommended-function-values (Section 13.1);
    • <mark>.<fv>.cumtrapz, the cumulative trapezoidal integration (Chapter 9) of the recommended-function-values;
    • <mark>.<fv>.cumvtrapz, the cumulative average vertical height of trapezoidal integration (Section 9.1) of the recommended-function-values.

The examples below shows truncation at different location for Chapter 3, Listing 3.1, Listing 3.2,

Example: function summary_fv(rmax = 220)
out |> summary_fv(rmax = 220)
Example: function summary_fv(rmax = 260)
out |> summary_fv(rmax = 260)

The S3 method dispatch t.vectorlist() (Section 27.3) is the fastest way to extract a “slice” from a numeric-hypercolumn, e.g., out_fv$hladr.E.cumvtrapz from Chapter 3, Listing 3.1, Listing 3.2, Listing 3.3. The numeric-hypercolumns created by function summary_fv() are 'vectorlist's (although not supported as hypercolumns in hyperframe as of package spatstat.geom v3.6.0.3), as they contain tabulated values on common \(r\)-vector(s). A “slice” of the hypercolumn out_fv$hladr.E.cumvtrapz at the 5th index of the \(r\)-vector, i.e., \(r=50\), may be extracted by calling the S3 method dispatch spatstat.geom::with.hyperframe(), but the S3 method dispatch t.vectorlist() is much faster.

Example: function t.vectorlist(); a ‘slice’ from hypercolumn out_fv$hladr.E.cumvtrapz
if (FALSE) {
E_r50_a = out_fv |>
  spatstat.geom::with.hyperframe(expr = {
    hladr.E.cumvtrapz['50']
  })
E_r50_a
E_r50_b = out_fv |>
  spatstat.geom::with.hyperframe(expr = {
    hladr.E.cumvtrapz[5L]
  })
stopifnot(identical(E_r50_a, E_r50_b))
tE = out_fv$hladr.E.cumvtrapz |>
  t.vectorlist()
stopifnot(identical(E_r50_a, tE[[5L]]))
}

17.11 Handling Illegal Recommended-Function-Value

The S3 generic functions .illegal2theo() and .disrecommend2theo() have been introduced in Section 13.3.1.

The S3 method dispatches .illegal2theo.hyperframe() and .disrecommend2theo.hyperframe() apply the S3 method dispatches .illegal2theo.fvlist() and .disrecommend2theo.fvlist() (Section 14.4) to its fv-hypercolumns that are fvlists.

Advanced: function .illegal2theo.hyperframe() and .disrecommend2theo.hyperframe()
# not written yet

17.12 \(k\)-Means Clustering

The S3 generic function .kmeans() has been introduced in Section 23.12. The S3 method dispatch .kmeans.hyperframe()

  • performs \(k\)-means clustering on the one-and-only-one (Section 17.13) ppp-hypercolumn via .kmeans.ppplist() (Section 24.6).
  • returns an object of class 'hyperframekm', which inherits from 'hyperframe'.

Package groupedHyperframe (v0.3.0.20251020) implements the following S3 method dispatches to the class 'hyperframekm' (Table 17.3),

Table: S3 method dispatches groupedHyperframe::*.hyperframekm
methods2kable(class = 'hyperframekm', package = 'groupedHyperframe', all.names = TRUE)
Table 17.3: S3 method dispatches groupedHyperframe::*.hyperframekm (v0.3.0.20251020)
visible from generic isS4
split.hyperframekm TRUE groupedHyperframe base::split FALSE

17.12.1 Examples

The authors use the hyper data frame flu (Section 8.10) to illustrate this usage.

Example: function .kmeans.hyperframe()
set.seed(13); flu_k = spatstat.data::flu |>
  spatstat.geom::subset.hyperframe(subset = (stain == 'M2-M1') & (virustype == 'wt')) |> 
  .kmeans(formula = ~ x + y, centers = 3L)
flu_k |>
  class()
# [1] "hyperframekm" "hyperframe"   "list"
flu_k$pattern[1:3]
# List of point patterns
# 
# wt M2-M1 13:
# Marked planar point pattern: 471 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm
# with k-means clustering of 153, 147, 171 points
# 
# wt M2-M1 22:
# Marked planar point pattern: 217 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm
# with k-means clustering of 85, 68, 64 points
# 
# wt M2-M1 27:
# Marked planar point pattern: 214 points
# Multitype, with levels = M2, M1 
# window: rectangle = [0, 3331] x [0, 3331] nm
# with k-means clustering of 84, 71, 59 points

17.12.2 Split by \(k\)-Means Clustering

The S3 method dispatch split.hyperframekm() splits a hyperframekm by the \(k\)-means clustering indices of the one-and-only-one (Section 17.13) ppp-hypercolumn. The returned object is a groupedHyperframe with grouping structure

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

The authors use the hyper data frame flu (Section 8.10) to illustrate this usage.

Example: function split.hyperframekm()
set.seed(13); spatstat.data::flu |>
  spatstat.geom::subset.hyperframe(subset = (stain == 'M2-M1') & (virustype == 'wt')) |> 
  .kmeans(formula = ~ x + y, centers = 3L) |> 
  split()
# Grouped Hyperframe: ~.id/.cluster
# 
# 24 .cluster nested in
# 8 .id
# 
# Preview of first 10 (or less) rows:
# 
#    pattern .id .cluster virustype stain frameid
# 1    (ppp)   1        1        wt M2-M1      13
# 2    (ppp)   1        2        wt M2-M1      13
# 3    (ppp)   1        3        wt M2-M1      13
# 4    (ppp)   2        1        wt M2-M1      22
# 5    (ppp)   2        2        wt M2-M1      22
# 6    (ppp)   2        3        wt M2-M1      22
# 7    (ppp)   3        1        wt M2-M1      27
# 8    (ppp)   3        2        wt M2-M1      27
# 9    (ppp)   3        3        wt M2-M1      27
# 10   (ppp)   4        1        wt M2-M1      43

17.13 Batch Process on Eligible marks

The S3 method dispatches Emark_.hyperframe(), Vmark_.hyperframe(), etc., in Table 17.1 are user-friendly wrappers of the low-level utility function op_hyperframe(), for batch operation on hyperframe (Section 3.2). Function op_hyperframe()

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