Skip to contents

Scope

This article demonstrates the restricted contiguous-motif workflow in gp3sequences. The workflow accepts ordinary long-format data frames and does not require Gazepoint software, hardware, exports, or gp3tools.

The functions describe recurring state windows and their locations. They do not infer attention, cognition, emotion, intention, psychological state, or causal mechanisms.

Synthetic ordered-state data

The example contains three sequences and one preserved grouping variable.

library(gp3sequences)

sequence_data <- data.frame(
  sequence = c(
    rep("s1", 5L),
    rep("s2", 4L),
    rep("s3", 3L)
  ),
  order = c(1:5, 1:4, 1:3),
  state = c(
    "A", "B", "A", "B", "C",
    "A", "B", "C", "B",
    "B", "A", "B"
  ),
  group = c(
    rep("g1", 5L),
    rep("g1", 4L),
    rep("g2", 3L)
  ),
  stringsAsFactors = FALSE
)

sequence_data
#>    sequence order state group
#> 1        s1     1     A    g1
#> 2        s1     2     B    g1
#> 3        s1     3     A    g1
#> 4        s1     4     B    g1
#> 5        s1     5     C    g1
#> 6        s2     1     A    g1
#> 7        s2     2     B    g1
#> 8        s2     3     C    g1
#> 9        s2     4     B    g1
#> 10       s3     1     B    g2
#> 11       s3     2     A    g2
#> 12       s3     3     B    g2

Extract contiguous motifs

extract_sequence_ngrams() enumerates contiguous state windows only. Minimum and maximum motif lengths and the overlapping-occurrence policy are explicit.

extracted <- extract_sequence_ngrams(
  sequence_data,
  sequence_id_col = "sequence",
  order_col = "order",
  state_col = "state",
  metadata_cols = "group",
  min_length = 2L,
  max_length = 3L,
  overlap = "allow"
)

head(extracted$occurrences)
#>   sequence_id group    motif_id motif_key     motif motif_length start_index
#> 1          s1    g1    L2:S1|S2     S1|S2     A > B            2           1
#> 2          s1    g1 L3:S1|S2|S1  S1|S2|S1 A > B > A            3           1
#> 3          s1    g1    L2:S2|S1     S2|S1     B > A            2           2
#> 4          s1    g1 L3:S2|S1|S2  S2|S1|S2 B > A > B            3           2
#> 5          s1    g1    L2:S1|S2     S1|S2     A > B            2           3
#> 6          s1    g1 L3:S1|S2|S3  S1|S2|S3 A > B > C            3           3
#>   end_index start_order end_order start_original_row end_original_row
#> 1         2           1         2                  1                2
#> 2         3           1         3                  1                3
#> 3         3           2         3                  2                3
#> 4         4           2         4                  2                4
#> 5         4           3         4                  3                4
#> 6         5           3         5                  3                5
#>   occurrence_index
#> 1                1
#> 2                1
#> 3                1
#> 4                1
#> 5                2
#> 6                1

Summarise, filter, and format motifs

Sequence prevalence uses every validated sequence as its denominator. Filtering is deterministic and retains explicit thresholds and tie handling.

motif_summary <- summarise_sequence_motifs(extracted)

motif_filter <- filter_sequence_motifs(
  motif_summary,
  min_occurrences = 2L,
  min_sequences = 2L,
  min_prevalence = 0.50,
  motif_lengths = c(2L, 3L),
  top_n = 10L,
  rank_by = "sequence_prevalence",
  ties = "include"
)

motif_table <- format_sequence_motifs(
  motif_filter,
  prevalence = "percent",
  digits = 1L
)

motif_table$table
#>   rank    motif_id motif_key     motif motif_length n_occurrences n_sequences
#> 1    1    L2:S1|S2     S1|S2     A > B            2             4           3
#> 2    2    L2:S2|S1     S2|S1     B > A            2             2           2
#> 3    2    L2:S2|S3     S2|S3     B > C            2             2           2
#> 4    2 L3:S1|S2|S3  S1|S2|S3 A > B > C            3             2           2
#> 5    2 L3:S2|S1|S2  S2|S1|S2 B > A > B            3             2           2
#>   sequence_prevalence_percent occurrence_share_percent
#> 1                       100.0                     26.7
#> 2                        66.7                     13.3
#> 3                        66.7                     13.3
#> 4                        66.7                     13.3
#> 5                        66.7                     13.3
#>   mean_occurrences_per_sequence mean_occurrences_when_present
#> 1                           1.3                           1.3
#> 2                           0.7                           1.0
#> 3                           0.7                           1.0
#> 4                           0.7                           1.0
#> 5                           0.7                           1.0

Summarise motif positions

Positions may represent the start, centre, or end of each motif occurrence. Absolute positions use one-based state indices. Relative positions range from 0 to 1 across each sequence.

position_summary <- summarise_sequence_motif_positions(
  extracted,
  position = "centre",
  scale = "relative",
  by = "group"
)

position_summary$summary
#>    group    motif_id motif_key     motif motif_length position_basis
#> 1     g1 L3:S1|S2|S1  S1|S2|S1 A > B > A            3         centre
#> 2     g1    L2:S1|S2     S1|S2     A > B            2         centre
#> 3     g1    L2:S2|S1     S2|S1     B > A            2         centre
#> 4     g1 L3:S2|S1|S2  S2|S1|S2 B > A > B            3         centre
#> 5     g1 L3:S1|S2|S3  S1|S2|S3 A > B > C            3         centre
#> 6     g1 L3:S2|S3|S2  S2|S3|S2 B > C > B            3         centre
#> 7     g1    L2:S2|S3     S2|S3     B > C            2         centre
#> 8     g1    L2:S3|S2     S3|S2     C > B            2         centre
#> 9     g2    L2:S2|S1     S2|S1     B > A            2         centre
#> 10    g2 L3:S2|S1|S2  S2|S1|S2 B > A > B            3         centre
#> 11    g2    L2:S1|S2     S1|S2     A > B            2         centre
#>    position_scale n_occurrences n_sequences min_position max_position
#> 1        relative             1           1    0.2500000    0.2500000
#> 2        relative             3           2    0.1250000    0.6250000
#> 3        relative             1           1    0.3750000    0.3750000
#> 4        relative             1           1    0.5000000    0.5000000
#> 5        relative             2           2    0.3333333    0.7500000
#> 6        relative             1           1    0.6666667    0.6666667
#> 7        relative             2           2    0.5000000    0.8750000
#> 8        relative             1           1    0.8333333    0.8333333
#> 9        relative             1           1    0.2500000    0.2500000
#> 10       relative             1           1    0.5000000    0.5000000
#> 11       relative             1           1    0.7500000    0.7500000
#>    mean_position median_position
#> 1      0.2500000       0.2500000
#> 2      0.3055556       0.1666667
#> 3      0.3750000       0.3750000
#> 4      0.5000000       0.5000000
#> 5      0.5416667       0.5416667
#> 6      0.6666667       0.6666667
#> 7      0.6875000       0.6875000
#> 8      0.8333333       0.8333333
#> 9      0.2500000       0.2500000
#> 10     0.5000000       0.5000000
#> 11     0.7500000       0.7500000

format_sequence_motif_positions() changes display precision and units without modifying the underlying analytical object.

position_table <- format_sequence_motif_positions(
  position_summary,
  digits = 1L,
  position_units = "percent",
  include_rank = TRUE
)

position_table$table
#>    group rank    motif_id motif_key     motif motif_length position_basis
#> 1     g1    1 L3:S1|S2|S1  S1|S2|S1 A > B > A            3         centre
#> 2     g1    2    L2:S1|S2     S1|S2     A > B            2         centre
#> 3     g1    3    L2:S2|S1     S2|S1     B > A            2         centre
#> 4     g1    4 L3:S2|S1|S2  S2|S1|S2 B > A > B            3         centre
#> 5     g1    5 L3:S1|S2|S3  S1|S2|S3 A > B > C            3         centre
#> 6     g1    6 L3:S2|S3|S2  S2|S3|S2 B > C > B            3         centre
#> 7     g1    7    L2:S2|S3     S2|S3     B > C            2         centre
#> 8     g1    8    L2:S3|S2     S3|S2     C > B            2         centre
#> 9     g2    1    L2:S2|S1     S2|S1     B > A            2         centre
#> 10    g2    2 L3:S2|S1|S2  S2|S1|S2 B > A > B            3         centre
#> 11    g2    3    L2:S1|S2     S1|S2     A > B            2         centre
#>    position_scale position_unit n_occurrences n_sequences min_position
#> 1        relative       percent             1           1         25.0
#> 2        relative       percent             3           2         12.5
#> 3        relative       percent             1           1         37.5
#> 4        relative       percent             1           1         50.0
#> 5        relative       percent             2           2         33.3
#> 6        relative       percent             1           1         66.7
#> 7        relative       percent             2           2         50.0
#> 8        relative       percent             1           1         83.3
#> 9        relative       percent             1           1         25.0
#> 10       relative       percent             1           1         50.0
#> 11       relative       percent             1           1         75.0
#>    max_position mean_position median_position
#> 1          25.0          25.0            25.0
#> 2          62.5          30.6            16.7
#> 3          37.5          37.5            37.5
#> 4          50.0          50.0            50.0
#> 5          75.0          54.2            54.2
#> 6          66.7          66.7            66.7
#> 7          87.5          68.8            68.8
#> 8          83.3          83.3            83.3
#> 9          25.0          25.0            25.0
#> 10         50.0          50.0            50.0
#> 11         75.0          75.0            75.0

Plot motif prevalence

plot_sequence_motifs() uses base R graphics. The returned data frame contains the exact motifs and values used in the plot.

plotted_motifs <- plot_sequence_motifs(
  motif_summary,
  metric = "sequence_prevalence",
  top_n = 8L,
  motif_lengths = c(2L, 3L),
  ties = "include",
  horizontal = TRUE
)
Sequence prevalence for the most frequent contiguous motifs.

Sequence prevalence for the most frequent contiguous motifs.


plotted_motifs[
  c("plot_rank", "motif", "motif_length", "plot_value")
]
#>   plot_rank     motif motif_length plot_value
#> 1         1     A > B            2  1.0000000
#> 2         2     B > A            2  0.6666667
#> 3         3     B > C            2  0.6666667
#> 4         4 A > B > C            3  0.6666667
#> 5         5 B > A > B            3  0.6666667
#> 6         6     C > B            2  0.3333333
#> 7         7 A > B > A            3  0.3333333
#> 8         8 B > C > B            3  0.3333333

Plot motif locations

The strip display shows individual occurrence positions with deterministic stacking. No random jitter is used.

strip_data <- plot_sequence_motif_positions(
  extracted,
  position = "centre",
  scale = "relative",
  top_n = 5L,
  display = "strip"
)
Relative centre positions of selected motif occurrences.

Relative centre positions of selected motif occurrences.


head(
  strip_data[
    c(
      "sequence_id",
      "motif",
      "position_value",
      "plot_rank"
    )
  ]
)
#>   sequence_id motif position_value plot_rank
#> 1          s1 A > B      0.1250000         1
#> 2          s2 A > B      0.1666667         1
#> 3          s1 A > B      0.6250000         1
#> 4          s3 A > B      0.7500000         1
#> 5          s3 B > A      0.2500000         2
#> 6          s1 B > A      0.3750000         2

The distribution display provides a compact base-R summary for the same structural positions.

plot_sequence_motif_positions(
  extracted,
  position = "centre",
  scale = "relative",
  top_n = 5L,
  display = "distribution"
)
Distributions of relative motif centre positions.

Distributions of relative motif centre positions.

Interpretation boundary

The reported counts, prevalence values, and positions describe the supplied ordered states under the declared preparation, motif-length, overlap, filtering, and position rules. Any substantive interpretation belongs to the research design and cannot be inferred automatically from motif structure alone.