| transition_audit | R Documentation |
Builds a stable, documented audit / provenance record describing what happened to the edges and weights as [pagerank()] turned a raw edge list into the transition graph it scored. It is the backbone of reproducibility and of downstream diagnostics: it carries the row/edge counts, behavioral-weight coverage, normalization totals, the data that was dropped along the way (rows lost to NA / deduplication / self-loop removal, and authority-prior URLs that never folded onto a vertex), and the relevant [pagerank()] configuration. It also records the duplicate-edge policy used to build transitions, so callers can distinguish the default destination-level surfer from opt-in aggregate / link-slot models.
## Structure and contract
The object is an S3 list with class '"transition_audit"' (a list was chosen over a bare list so that it prints a human-readable summary while remaining a plain, inspectable 'list' for programmatic access — 'audit$counts$n_edges' works as expected, mirroring the existing [audit_redirects()] / [audit_canonicals()] objects in this package). The documented top-level fields are **stable**; callers may rely on them being present.
A list of integer counts: 'n_input_rows' (rows in the raw 'edge_list_df'), 'n_edges' (directed edges remaining after URL folding, deduplication and self-loop handling — i.e. the edges actually scored), and 'n_vertices' (vertices in the returned result).
A list describing behavioral-weight coverage: 'weighted' (logical, whether a 'weight_col' was in effect), 'weight_col' (its name or 'NULL'), 'n_edges_weighted' (edges carrying a finite, positive weight), and 'coverage' (the fraction 'n_edges_weighted / n_edges', or 'NA_real_' when there are no edges / no weighting).
A list of normalization totals: 'pagerank_total' (sum of the returned PageRank scores; '< 1' when mass evaporated via nofollow, vanished robots-blocked pages, etc.).
A list accounting for data removed during construction: 'n_rows_na' (input rows dropped because 'from'/'to' was 'NA'), 'n_rows_duplicate' (rows collapsed by edge deduplication), 'n_self_loops' (self-loop edges dropped when 'self_loops = "drop"'), 'n_rows_collapsed' (total input rows that did not survive as distinct scored edges = 'n_input_rows - n_edges'), 'n_prior_unmatched' (authority prior URLs that did not fold onto any vertex; 'NA_integer_' when no 'prior_df' was supplied), 'n_robots_blocked' (URLs treated as robots.txt-blocked), and 'n_status_dead' (in-graph URLs whose HTTP status code marked them response-dead; '0' when no 'status_df' was supplied).
A list describing duplicate-edge handling: 'policy' (the 'duplicate_edge_policy' passed to [pagerank()]), 'n_duplicate_rows' (post-fold duplicate input rows), 'instance_count_col' (the internal audit column used by '"count_instances"', or 'NULL'), and 'n_duplicate_instances' (the number of duplicate link instances folded into transition weights), and 'duplicate_edges' (a compact data frame of counted edges with more than one link instance, or 'NULL').
A list of the [pagerank()] arguments that materially shape the transition graph. 'preset' records the *provenance* of the rest: the name of the [pr_preset()] bundle the caller asked for (e.g. '"declared"'), '"custom"' for a hand-rolled bundle, or 'NULL' when no preset was used — so a run made as a named view stays distinguishable from the same arguments typed out by hand. 'placement' records placement-aware weighting when it was used ('placement_col', 'accepted_placements', 'placement_weights', and 'n_rows_dropped', the number of edge rows the placement filter removed), or 'NULL' when it was not — so a downweighted edge can be explained by the region it sits in rather than only by the opaque weight column it produced. 'boilerplate' records the recurrence detector the same way when it was used ('container_col', 'boilerplate_threshold', 'min_container_pages', 'boilerplate_weight', and the counts 'n_containers', 'n_edges_scored', 'n_edges_judged' and 'n_edges_discounted'), or 'NULL' when it was not. Placement and recurrence are two detectors feeding one graded axis, and the strongest applicable discount wins, so both are recorded **separately**: the resulting weight alone cannot say which detector produced it. 'position' records the orthogonal reading-order axis the same way when it was used ('position_col', 'position_transform', 'position_alpha', 'position_floor', and the counts 'n_edges_scored', 'n_sources_scored', and 'min_position_weight'), or 'NULL' when it was not – it *multiplies* into the weight rather than competing for the minimum, so it too is recorded on its own so an edge weighing '0.02' can be explained as region times reading order. The other fields are the resolved configuration itself: 'self_loops', 'drop_isolates_flag', 'reverse', 'weight_col', 'nofollow_col', 'nofollow_action', 'robots_blocked_action', 'prior_alpha', 'prior_transform', 'prior_inject_unmatched', and the logical flags 'has_redirects' / 'has_canonicals' (whether that signal *materially* folded an edge — an effective no-op such as a self-canonical reads 'FALSE'), 'has_indexability', and 'has_prior'.
A list decomposing the internal stationary vector (which always sums to 1) into its accounted-for components: 'reported' (the mass on returned, visible pages — equals the summed result scores), 'sink' (the **evaporated mass**: authority routed to the shared waste sink — what the whole waste class (noindex / robots-blocked / 4xx-5xx) and every real nofollowed link under 'nofollow_action = "evaporate"' passed on but could not deliver), 'leaked' (the **leaked mass**: authority sent to the synthetic leak sink under 'out_of_scope_fold = "leak"', i.e. equity that flowed into out-of-scope-folded sources and left the measured graph — '0' when no leak occurred), 'hidden' (the **hidden mass**: the own stationary mass of robots-blocked nodes removed under 'robots_blocked_action = "vanish"'; their pass-through still routes to the waste sink and is counted in 'sink'), and 'total' (their sum, which reconciles to 1 by construction). These are the precise components of the deficit between the reported scores and 1 — it is evaporated, leaked and hidden mass, not undifferentiated "leakage". Each is 'NULL' when the stationary vector is undefined (e.g. an empty graph).
A list recording how **out-of-scope folds** were handled — a composed fold-map entry whose *target* (the representative a crawled source folds onto) is not itself a crawled node, which silently invents a phantom vertex. 'policy' (the 'out_of_scope_fold' argument, '"relabel"', '"keep"' or '"leak"'), 'n_out_of_scope' (count of such entries), 'applied' (logical: 'TRUE' when they were acted upon — relabeled / folded through under '"relabel"', or routed to the leak sink under '"leak"' — and 'FALSE' when skipped / kept as crawled under '"keep"'; combine with 'policy' to distinguish relabel from leak), and 'out_of_scope' (a data frame of the offending 'source' / 'target' / 'signal' rows, or 'NULL' when there were none), and 'collisions' (a data frame of **fold-target collisions** — uncrawled URLs that a fold relabeled a crawled source onto while they were ALSO independently linked, so the two silently merge into one vertex and the crawled page absorbs the inbound link equity of that uncrawled URL; columns 'target', 'n_independent_refs' and the folded 'source'(s) — or 'NULL' when none). A collision triggers a 'warning()' naming the merged URL(s). This diagnostic requires crawl-URL knowledge to distinguish an uncrawled fold target from a genuinely crawled leaf page, so it is only computed when an 'indexability_df' is supplied to [pagerank()]; without it, 'collisions' is 'NULL'. Recorded regardless of 'out_of_scope_fold' policy.
The constructor [new_transition_audit()] is internal plumbing for [pagerank()]; the object is normally obtained via 'attr(result, "transition_audit")' (see [pagerank()]).
[pagerank()], [audit_redirects()], [audit_canonicals()]
# A transition_audit is attached to every pagerank() result, and explains
# what happened between the raw edge list and the graph actually scored.
edges <- data.frame(
from = c("/a", "/a", "/b", "/b", "/c", NA),
to = c("/b", "/b", "/c", "/b", "/a", "/a")
)
result <- pagerank(edges, self_loops = "drop")
audit <- attr(result, "transition_audit")
audit
# The documented top-level fields are stable, so callers can rely on them.
audit$counts$n_input_rows # 6 raw rows in ...
audit$counts$n_edges # ... 3 distinct edges scored
# Each collapsed row is accounted for individually.
audit$dropped$n_rows_na # the NA-endpoint row
audit$dropped$n_rows_duplicate # the repeated /a -> /b row
audit$dropped$n_self_loops # the /b -> /b self-loop
# Mass accounting: the internal stationary vector always sums to 1, split
# into reported (visible) mass plus whatever evaporated / leaked / hid.
audit$mass$reported
audit$mass$total
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.