Hubs collocate records across classification

A library shelves each book once, by class. Oliver Sacks’s case studies The man who mistook his wife for a hat sit in R (medicine); Michael Nyman’s chamber opera of the same name sits in M (music), so classification splits them. LC subject headings don’t rejoin them either. Subject headings group records by what they are about: the book has Neurology — Anecdotes, the opera Operas — Scores and Visual agnosia — Drama. The one existing link is inside the opera’s records: an added entry for Sacks, Oliver. Man who mistook his wife for a hat…. It points one way, appears only in the opera’s records, and doesn’t say how the two are related.

Library of Congress BIBFRAME Hubs turn that into a link between the works themselves. A Hub is the authorized heading for a work (Sacks, Oliver. Man who mistook his wife for a hat) with a URI, and Hubs carry typed relationships to each other: opera adaptation of, based on, libretto for. Once bibliographic records are attached to their Hubs, every record of the book is one typed hop from every record of the opera, whatever shelf or subject headings each has. Section 2 checks how often subject headings or a record’s own added entries already connect such pairs.

This page shows that, using 437,836 LC bibliographic records matched to their Hub at high confidence (about 96% exactly right in a hand check). The match is the bib_to_hub table in jimfhahn/lc-bibframe-hubs; the records come from LC’s experimental embeddings release (jimfhahn/lc-bib-embeddings, 12.2M records). Everything runs in your browser. To browse any Hub’s whole family, use the Hub family explorer.

One gap to keep in mind: the source has no class P (language and literature) and no T (technology) yet, because LC’s files for them are not downloadable. P is where most adaptations start, so every count here is a floor.

// Four small Parquet files (~0.5 MB) written by tools/bib-hub-mapping/build_bib_to_hub.py
// --collocation. Same loader as the Hub family explorer: a same-origin copy in ./data/
// first (deploy-space.sh puts it there), then the dataset repo.
const DATASET = "https://huggingface.co/datasets/jimfhahn/lc-bibframe-hubs/resolve/main/collocation/";
const SOURCES = [new URL("./data/", location.href).href, DATASET];
const db = await DuckDBClient.of();
const isParquet = (b) => b.length > 8 && b[0] === 0x50 && b[1] === 0x41 && b[2] === 0x52 && b[3] === 0x31; // "PAR1"
async function attach(name) {
  const errors = [];
  for (const base of SOURCES) {
    try {
      const res = await fetch(base + name);
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const bytes = new Uint8Array(await res.arrayBuffer());
      if (!isParquet(bytes)) throw new Error("not a Parquet file");
      return db._db.registerFileBuffer(name, bytes);
    } catch (e) {
      errors.push(`${base}${name}: ${e.message}`);
    }
  }
  throw new Error(`Could not load ${name}:\n${errors.join("\n")}`);
}
const FILES = {hub_class: "colloc_hub_class.parquet", edges: "colloc_edges.parquet",
               records: "colloc_records.parquet", coverage: "colloc_coverage.parquet"};
await Promise.all(Object.values(FILES).map(attach));
for (const [table, file] of Object.entries(FILES)) {
  await db.query(`CREATE TABLE ${table} AS SELECT * FROM read_parquet('${file}')`);
}

1. One work, two shelves

Pick a pair of works joined by a creative relationship. Each side lists the LC records matched to that work’s Hub, grouped by the class they are shelved in. Titles link to LC’s BIBFRAME description of the record; the work names open the Hub in the family explorer.

const SACKS = "a9402977-4b49-89c3-e703-6f4e0c969790";
const pair = view(Inputs.select(crossPairs, {
  label: "Pair",
  value: crossPairs.find((p) => p.a === SACKS || p.b === SACKS),
  format: (p) => `${trunc(shortHub(p.from), 45)}  →  ${p.relText}  →  ${trunc(shortHub(p.to), 45)}`
}));

Each row is a pair of works joined by a creative relationship (adaptation, libretto, musical setting, based on…) where both works have matched LC records and the records sit in different classes. Dots show where each work’s records are shelved; the grey line is the distance the Hub relationship bridges. Columns P and T are empty because the source has no records there; the novels and plays that do appear sit in A because LC classes collected sets such as Great Books of the Western World (AC1 .G72) and some translation series there.

Don’t subject headings already do this? Sometimes. We checked these 40 pairs against LC’s MARC records (up to five per side, October 2026). The two sides share an identical LCSH heading in only 3 pairs (Faust, -approximately 1540 — Drama; Othello (Fictitious character from Shakespeare) — Drama; Operas — Librettos). They share a main heading in 14, mostly a person or character both works are about (Alexander Hamilton, Benvenuto Cellini, Athaliah, Mongkut) or a broad form (Operas; Hymns, English). Subject headings collocate by topic, which complements Hubs, but they rarely record that one work adapts another.

The closer equivalent is in the records themselves. In 28 pairs, a record on one side names the other work in a name/title entry (600/700/730), sometimes with a relationship designator (Ellington’s Beautiful Indians: Inspired by (work): Longfellow, Henry Wadsworth. Song of Hiawatha). That link is one-way and attached to that record only. The Hub relationship joins every record on both sides. In the other 12 pairs no record names the other work, so the Hub is the only link between them, apart from four that share a main heading (Cellini, Benvenuto twice; Operas; Hymns, English). Most are 19th-century stage works: Scribe and Boieldieu’s La dame blanche after Scott’s Monastery and Abbot, Gevaert’s Quentin Durward, Bishop’s Heart of Mid-Lothian, Solomon’s Pickwick, Lassen’s Faust music. Script: tools/bib-hub-mapping/lcsh_overlap.py.

3. One work, many shelves

Collocation also happens on a single Hub: one work whose editions LC classed under different subjects. The U.S. Constitution sits in general works, American history, political science and law; Machiavelli’s Prince, Franklin’s Autobiography and Hobbes’s Leviathan each span three classes. Collective titles (Works. Selections, Essays) gather different books by one author rather than one work, so they are hidden by default. Many of these Hubs (Prince, Autobiography) have no links to other Hubs, so their table link goes to id.loc.gov rather than the family explorer.

const hideCollective = view(Inputs.toggle({label: "Hide collective titles", value: true}));
const topN = view(Inputs.range([10, 60], {label: "Works shown", step: 5, value: 25}));

4. How much of the catalogue this reaches

Share of each class’s records matched to a Hub. Music leads because composers’ works are almost always under uniform titles; most other classes sit at 2–5%. A record can only be matched where LC made a name/title authority for its work.

5. How far to trust it

Records were matched offline: each record’s first creator and title (normalized, subtitle dropped) against each Hub’s authorized access point, then against the Hub’s variant titles, which catches translations (Studies on the development of consciousness → Chesni, Recherches sur le développement de la conscience). A stratified sample of 300 matches was checked against LC’s own BIBFRAME Work links and, where LC links none, by hand.

confidence records exactly the right Hub right work
high (used on this page) 437,836 96.5% (95% CI 93–98%) 99%
medium: several Hubs tie 30,425 66% 78%
low: title-only or name-only matches 25,070 66% 72%

Two error patterns are labelled down rather than counted: titles that are just the creator’s name (exhibition catalogues called Picasso gathered on one Picasso, Pablo. Picasso Hub), and series whose volumes share a main title (Chicken soup for the soul : …), which show up as one Hub spread over many classes with a different subtitle on almost every record. Method, columns and every hand-checked row are on the dataset card.


About

Data. Library of Congress BIBFRAME Hubs bulk dump (2026-05-05) and LC’s experimental bibliographic embeddings (2025), both in the public domain, repackaged as Parquet: lc-bibframe-hubs (including bib_to_hub and the four small collocation/ files this page loads) and lc-bib-embeddings. “Creative relationship” means the surprise tiers 1–3 used by the companion VuFind plugin: transformations and parodies, cross-medium adaptations, sequels and based on.

Code. tools/bib-hub-mapping/ builds the match and these files; this page is notebooks/hub-collocation.html (Observable Notebook Kit). Tables loaded in the browser: hub_class(hub_id, label, hub_name, hub_title, lcc_class, n, hub_total, hub_classes, hub_links), edges(source_id, target_id, rel_type), records(lc_001, hub_id, lcc_class, title, creator), coverage(lcc_class, records, high, medium, low).