Skip to contents

Computes Kleinberg's HITS hub and authority scores over the same cleaned, redirect/canonical-folded, domain-filtered, deduplicated link graph that [pagerank()] builds, so node identities line up across the two centrality measures. Wraps `igraph::hits_scores()` (the non-deprecated successor of `igraph::hub_score()` / `igraph::authority_score()`).

Usage

hits(
  edge_list_df,
  redirects_df = NULL,
  clean_edge_urls = TRUE,
  clean_redirect_urls = TRUE,
  rurl_params = list(),
  self_loops = c("drop", "keep"),
  drop_isolates_flag = TRUE,
  weight_col = NULL,
  duplicate_edge_policy = c("collapse", "aggregate", "count_instances"),
  edge_from_col = "from",
  edge_to_col = "to",
  redirect_from_col = "from",
  redirect_to_col = "to",
  duplicate_from_policy = c("strict", "first_wins", "last_wins", "most_frequent",
    "prune_source", "resolve_if_consistent"),
  loop_handling = c("error", "prune_loop", "break_arrow"),
  canonicals_df = NULL,
  canonical_from_col = "from",
  canonical_to_col = "to",
  clean_canonical_urls = TRUE,
  canonical_duplicate_from_policy = c("strict", "first_wins", "last_wins",
    "most_frequent", "prune_source", "resolve_if_consistent"),
  canonical_loop_handling = c("error", "prune_loop", "break_arrow"),
  canonical_conflict_policy = c("redirect_wins", "error", "canonical_wins"),
  keep_domains = NULL,
  exclude_domains = NULL,
  keep_hosts = NULL,
  exclude_hosts = NULL,
  scale = TRUE,
  ...
)

Arguments

edge_list_df

A data frame representing the edge list, typically with columns like "from" and "to".

redirects_df

An optional data frame for redirect rules, typically with "from" and "to" columns. Defaults to NULL.

clean_edge_urls

Logical, whether to clean URLs in the edge list. Defaults to TRUE.

clean_redirect_urls

Logical, whether to clean URLs in the redirect list. Defaults to TRUE. Only effective if `redirects_df` is provided.

rurl_params

A list of parameters to pass to `rurl::clean_url`. Defaults to an empty list. `protocol_handling` defaults to `"keep"` and `case_handling` to `"lower_host"` for cross-project canonicalization consistency. If you set `host_encoding` (`"idna"` or `"unicode"`) to fold internationalized (IDN) hosts, that same value is also passed to the domain-filtering step so its comparisons stay consistent with the cleaned node keys. (Registrable-domain matching is encoding-independent, so this only matters if host-level filtering is involved.)

self_loops

A character string specifying how to handle self-loops. Either "drop" (default) or "keep".

drop_isolates_flag

Logical, whether to drop isolated nodes before PageRank computation. Defaults to TRUE.

weight_col

Optional name of a numeric column in `edge_list_df` containing edge weights. Higher weights make edges more likely to be followed. If `NULL` (default), all edges have equal weight.

duplicate_edge_policy

How repeated `from -> to` rows are represented after URL cleaning, redirect/canonical folding, and domain filtering. One of:

`"collapse"`

(default) Destination-level surfer: repeated rows collapse to one unweighted destination edge, preserving legacy `get_unique_edges()` behavior and the common binary PageRank convention.

`"aggregate"`

Collapse each `from -> to` pair with [aggregate_edges()] semantics. Numeric columns, including `weight_col`, are summed; logical columns such as `nofollow` use the default `"any"` conflict policy.

`"count_instances"`

Link-slot / edge-level surfer: repeated rows increase transition probability. With no `weight_col`, each surviving `from -> to` pair receives an internal weight equal to its duplicate-row count. With `weight_col`, weights are summed and an `instance_count` audit column is retained.

edge_from_col, edge_to_col

Names of from/to columns in `edge_list_df`.

redirect_from_col, redirect_to_col

Names of from/to columns in `redirects_df`.

duplicate_from_policy

How to handle conflicting redirects in `redirects_df`. Passed through to [resolve_redirects()]. Default `"strict"` (error on conflicts). See [resolve_redirects()] for all available policies.

loop_handling

How to handle redirect cycles. Passed through to [resolve_redirects()]. Default `"error"`. See [resolve_redirects()] for all available policies.

canonicals_df

An optional data frame of declared `rel=canonical` links, with `from`/`to` columns (or as set by `canonical_from_col` / `canonical_to_col`) pairing a source URL with the canonical it declares. Default `NULL` (opt-in; the default preserves current behavior). Canonicals are a **distinct, advisory** signal from enforced 3xx `redirects_df`: they are tracked separately and audited via [audit_canonicals()] / [audit_fold()], then folded into the same composed map as redirects (see [build_fold_map()]). Self-canonicals drop as no-ops.

canonical_from_col, canonical_to_col

From/to columns in `canonicals_df`. Default `"from"` / `"to"`.

clean_canonical_urls

Logical, whether to clean URLs in `canonicals_df` using the same resolved `rurl_params` profile as edge and redirect cleaning. Default `TRUE`. Only effective when `canonicals_df` is provided.

canonical_duplicate_from_policy

How to handle a canonical source that declares multiple distinct canonicals. Reuses the `duplicate_from_policy` enum (see [resolve_redirects()]). Default `"strict"`.

canonical_loop_handling

How to handle cycles among declared canonicals. Reuses the `loop_handling` enum. Default `"error"`.

canonical_conflict_policy

How to resolve a redirect-vs-canonical disagreement on the **same source** URL. One of `"redirect_wins"` (default; the 3xx wins and the canonical on a redirecting source is ignored and flagged), `"error"` (error on genuine disagreement), or `"canonical_wins"` (the declared canonical wins for that source, still flagged). See [build_fold_map()].

keep_domains

Optional character vector of domains to keep. When provided, edges are filtered via [filter_links_by_domain()] so that only links where both endpoints belong to one of the specified domains are included. Useful for restricting to internal links. Default `NULL` (no domain filtering).

**Ordering:** filtering runs *after* redirect/canonical folding, so it scopes the post-fold (canonical) namespace, not the crawled input. If an out-of-scope canonical/redirect rewrites the crawled domain onto a different one, filtering on the crawled domain matches nothing (an empty graph). To scope the INPUT you crawled, run [filter_links_by_domain()] on the edge list *before* calling `pagerank()`.

exclude_domains

Optional character vector of domains to exclude. Edges where either endpoint belongs to one of these domains are removed. Like `keep_domains`, this filters the post-fold namespace (see the ordering note above). Default `NULL` (no exclusion).

keep_hosts

Optional character vector of exact hosts to keep (e.g. `"www.example.com"`), as opposed to registrable domains. Matched on the exact host using the same canonicalization profile as cleaning, so IDN folding (`host_encoding` in `rurl_params`) applies consistently. Default `NULL`.

exclude_hosts

Optional character vector of exact hosts to exclude. Edges where either endpoint matches one of these hosts are removed. Ignore rules override keep rules. Default `NULL`.

scale

Logical, passed to `igraph::hits_scores()` via [compute_hits()]. `TRUE` (default) scales each score so its maximum is `1`; `FALSE` returns the unit-norm eigenvectors. See [compute_hits()].

...

Additional arguments forwarded to [compute_hits()] and then to `igraph::hits_scores()`.

Value

A data frame with one row per node and columns `node_name`, `hub`, and `authority` (column names configurable via `...`). Hub and authority are scaled to a maximum of `1` by default (`scale = TRUE`).

Details

## Relationship to the PageRank pipeline

`hits()` reuses the exact identity-forming steps of [pagerank()] — URL canonicalization (the same resolved `rurl` profile), the same composed redirect + canonical fold map, the same domain/host filtering, the same `duplicate_edge_policy` deduplication, and the same self-loop / isolate handling. The resulting vertex set therefore matches `pagerank()` run with the same arguments, so hub, authority, and PageRank can be joined on `node_name` without re-canonicalizing.

The PageRank-specific, *forward-flow* modeling devices have **no HITS analogue and are intentionally not exposed**: nofollow evaporation, the indexability (noindex / robots.txt) transforms, the TIPR teleport prior, and the `reverse` flag. HITS already computes both directions of authority flow (hub is the outflow-oriented score, authority the inflow-oriented one), so a separate reversal is unnecessary.

## Matrix formulation and the whole-graph caveat

With adjacency matrix \(A\), **authority** is the dominant eigenvector of \(A^\top A\) ("pages pointed to by pages that point to many things") and **hub** is the dominant eigenvector of \(A A^\top\) ("pages that point to pages pointed to by many things"). See [compute_hits()].

Kleinberg's original HITS (1999) was run on a small, **query-focused base set** of pages, where the hub/authority distinction is sharply interpretable. `hits()` instead runs on the **full (or user-filtered) site graph** that `pagerankr` assembles. The eigenvector computation is identical and correct, but the interpretation shifts: scores describe hub/authority structure across the whole crawled graph rather than relevance to a specific query. Treat them as site-wide structural centralities, not query-relevance scores.

See also

[compute_hits()] for the computational core, [pagerank()] for the PageRank analogue sharing this identity pipeline.

Examples

edges <- data.frame(
  from = c("http://A.com/", "http://A.com/", "B.com"),
  to = c("B.com", "C.com", "C.com")
)
hits(edges)
#>       node_name      hub authority
#> 1 http://a.com/ 1.000000  0.000000
#> 2 http://b.com/ 0.618034  0.618034
#> 3 http://c.com/ 0.000000  1.000000

# Hub vs authority: a pure outflow page tops hub, a pure inflow page tops
# authority.
h <- hits(edges)
h[which.max(h$hub), ]
#>       node_name hub authority
#> 1 http://a.com/   1         0
h[which.max(h$authority), ]
#>       node_name          hub authority
#> 3 http://c.com/ 1.019645e-18         1