Skip to contents

Sweeps [pagerank()] over a grid of damping factors with [damping_sensitivity()] and compares each \(\alpha\)'s ranking against a reference \(\alpha\) with [compare_pagerank()], returning a one-row-per- \(\alpha\) stability summary. It answers the open question flagged in the "Damping factor" section of [pagerank()]: on *your* graph, how much does the ranking actually move as \(\alpha\) varies?

Usage

pagerank_stability(
  edge_list_df,
  alphas = c(0.75, 0.8, 0.85, 0.9, 0.95),
  reference = 0.85,
  top_k = 10,
  ...
)

Arguments

edge_list_df

A data frame representing the edge list, passed to every [pagerank()] call. (Named for consistency with the rest of the package; it is an edge list, not a constructed graph object.)

alphas

Numeric vector of damping factors to sweep, each strictly between 0 and 1. Default `c(0.75, 0.80, 0.85, 0.90, 0.95)`. Duplicate values are dropped.

reference

The baseline damping factor every other \(\alpha\) is compared against. A single number strictly between 0 and 1, default `0.85`. Included in the sweep automatically if not already in `alphas`.

top_k

Size of the top-scoring set used for the `top_k_overlap` churn metric. Positive integer, default `10`.

...

Additional arguments forwarded to [damping_sensitivity()] and on to [pagerank()] (e.g. `redirects_df`, `weight_col`, `algo`, `prior_df`). Passing `damping` is an error, since `alphas` drives the damping factor.

Value

A data frame with one row per swept \(\alpha\) (ascending), with columns:

`alpha`

The damping factor.

`spearman_rho`

Spearman rank correlation of this \(\alpha\)'s ranking against the reference, on their common nodes (`NA` if fewer than 3 common nodes).

`mean_abs_delta`

Mean absolute score difference vs the reference on common nodes.

`top_k_overlap`

Fraction in `[0, 1]` of the reference's top-`k` pages that are also in this \(\alpha\)'s top-`k` (1 = identical top set). The effective `k` shrinks to the node count on small graphs.

`nodes_gained`, `nodes_lost`

Nodes present at this \(\alpha\) but not the reference, and vice versa. Normally 0: varying \(\alpha\) changes scores, not the node set.

`algo`, `iters`, `iters_estimate`, `residual`, `tol`, `converged`, `n_nodes`

The per-\(\alpha\) convergence metadata carried over from [damping_sensitivity()].

The full per-(URL, \(\alpha\)) sensitivity frame from [damping_sensitivity()] is attached as the `"sensitivity"` attribute, and the `reference` and `top_k` used are attached as same-named attributes.

Details

A Spearman rank correlation near 1 across the whole grid means the choice of damping factor is immaterial for this graph — the conventional `0.85` is as good as any nearby value. A low correlation, or a top-\(k\) overlap well below 1, flags a graph whose ranking is genuinely \(\alpha\)-sensitive and worth investigating before trusting any single solve.

This is a thin orchestration layer: it performs no PageRank math of its own, delegating the solves to [damping_sensitivity()] and the rank-comparison statistics to [compare_pagerank()]. The `reference` factor is always included in the sweep (even if absent from `alphas`) so it can serve as the comparison baseline; its own row is a sanity anchor (`spearman_rho = 1`, `mean_abs_delta = 0`, `top_k_overlap = 1`).

See also

[damping_sensitivity()], [compare_pagerank()], [pagerank()] (the "Damping factor" section)

Examples

edges <- data.frame(
  from = c("A", "B", "C", "A", "D"),
  to = c("B", "C", "A", "C", "A")
)
stab <- pagerank_stability(edges, clean_edge_urls = FALSE)
print(stab)
#>   alpha spearman_rho mean_abs_delta top_k_overlap nodes_gained nodes_lost
#> 1  0.75            1    0.013447950             1            0          0
#> 2  0.80            1    0.006689967             1            0          0
#> 3  0.85            1    0.000000000             1            0          0
#> 4  0.90            1    0.006628598             1            0          0
#> 5  0.95            1    0.013201832             1            0          0
#>     algo iters iters_estimate     residual   tol converged n_nodes
#> 1 prpack    NA             25 0.000000e+00 0.001      TRUE       4
#> 2 prpack    NA             31 5.551115e-17 0.001      TRUE       4
#> 3 prpack    NA             43 1.110223e-16 0.001      TRUE       4
#> 4 prpack    NA             66 8.673617e-17 0.001      TRUE       4
#> 5 prpack    NA            135 1.405126e-16 0.001      TRUE       4

# Drill into the per-(url, alpha) scores behind the summary.
head(attr(stab, "sensitivity"))
#>   url alpha     score iters iters_estimate     residual converged
#> 1   A  0.75 0.3769231    NA             25 0.000000e+00      TRUE
#> 2   C  0.75 0.3567308    NA             25 0.000000e+00      TRUE
#> 3   B  0.75 0.2038462    NA             25 0.000000e+00      TRUE
#> 4   D  0.75 0.0625000    NA             25 0.000000e+00      TRUE
#> 5   A  0.80 0.3820755    NA             31 5.551115e-17      TRUE
#> 6   C  0.80 0.3650943    NA             31 5.551115e-17      TRUE