Getting Started with bibnets

library(bibnets)

Introduction

bibnets constructs bibliometric networks from scholarly metadata. It imports the export formats of the major bibliographic databases, converts them internally to a common tabular representation, and projects that representation into networks through a single function per network type. The package covers the standard constructions and adds several that are less commonly available: position-based attention weighting, aggregation of entities into higher-level networks, a range of counting and similarity weights, and temporal construction over time windows.

Data import

bibnets reads Scopus, Web of Science, OpenAlex, Lens.org, Dimensions, Crossref, BibTeX, and RIS exports. read_biblio() detects the format from file content and dispatches to the corresponding reader; all readers return an identical schema, so records from different databases can be combined without manual reconciliation. Multi-valued fields — authors, references, and keywords — are parsed into list-columns. A data frame already in this form is used directly, by naming the relevant column, without a reader.

Network builders

Dedicated builders construct co-authorship, co-citation, bibliographic coupling, keyword co-occurrence, direct citation, and historiograph networks; a generic builder covers other projections. The builders share one interface and return the same edge list, so the network type is determined by the function name.

Weighting and aggregation

Counting methods determine each publication’s contribution to an edge. They range from full and fractional counting to position-aware schemes (harmonic, geometric, golden-ratio, first, last, and first–last), and six similarity measures — cosine, association strength, Jaccard, inclusion, and equivalence — rescale the projected weights.

Attention weighting assigns each author a positional weight that sums to one across the byline, so a publication’s credit is distributed by byline position rather than equally and a large author list does not dominate the network. Aggregation pools the references or members of a group to construct collaboration and coupling networks among countries, institutions, or sources rather than individuals. Temporal construction applies any builder over fixed, sliding, or cumulative windows, and a disparity-filter backbone retains the edges that are significant relative to each node’s strength.

Implementation

The incidence matrix is stored as a sparse dgCMatrix and projected with crossprod() or tcrossprod(); edges are extracted without forming a dense node-by-node matrix, so memory scales with the number of non-zero co-occurrences rather than with the square of the vocabulary. The package imports only Matrix, stats, and utils.

Export formats

Constructed networks are exported to igraph, tidygraph, cograph, Gephi, GraphML, and sparse-matrix representations.

Output

Every builder returns a bibnets_network: a tidy data frame with four columns —

With counting = "full" and similarity = "none", weight equals count. They diverge once fractional counting or a similarity measure is applied.

The builders, at a glance:

Function Nodes An edge means
author_network() authors co-authorship, author coupling, or co-citation
reference_network() cited references two references cited together
document_network() documents shared references, shared citers, or direct citation
keyword_network() keywords two keywords appear together
source_network() journals sources share references or are co-cited
country_network() countries countries collaborate or share references
institution_network() institutions institutions collaborate or share references
conetwork() any field entities co-occur, or share values of another field
local_citations() documents within-corpus citation counts
historiograph() documents directed citation history among top-cited papers
temporal_network() any builder’s nodes the same network over time windows

Quick start

You do not need a special reader. Any data frame with one row per paper works — point a builder at the column that holds the entity and tell it the delimiter:

papers <- data.frame(
  `Author Names` = c("Smith J, Doe A, Lee K", "Smith J, Lee K",
                     "Doe A, Lee K", "Smith J, Doe A"),
  check.names = FALSE
)

author_network(papers, authors = "Author Names", sep = ",")
#> # bibnets network: author_collaboration | 3 nodes · 3 edges | counting: full 
#>    from   to       weight  count
#> 1  DOE A  LEE K         2      2
#> 2  DOE A  SMITH J       2      2
#> 3  LEE K  SMITH J       2      2

If your data is a scholarly export instead, read it first — the format is detected from the file content — then build with the defaults:

data    <- read_biblio("scopus.csv")
authors <- author_network(data, type = "collaboration")

Either way the result is the same four-column edge list, ready to inspect, prune, or export.

Reading your own data

Scholarly exports

read_biblio() accepts a file, a folder, or several files, and detects Scopus, Web of Science, OpenAlex, BibTeX, RIS, Lens.org, and Dimensions from the content:

data <- read_biblio("export.csv")
data <- read_biblio("folder_with_exports/")
data <- read_biblio(c("part_1.csv", "part_2.csv"))

The format-specific readers can also be called directly (read_scopus(), read_wos(), read_openalex_csv(), read_dimensions(), read_lens(), read_bibtex(), read_ris()).

A custom CSV

For a CSV that matches no known export, map each source column onto a standard field by nameauthors, keywords, references, countries, affiliations, or journal. Naming any of them reads the file as a generic CSV, so you do not pass format yourself:

data <- read_biblio(
  "custom.csv",
  id       = "paper_id",
  authors  = "Author Names",
  keywords = "Tags",
  sep      = ","
)

Each mapped column is split on sep into the standard list-column, so afterwards every builder works with its defaults.

A plain data frame, directly

As the quick start showed, you can skip the reader entirely and let the builder split a column for you. The same column arguments are available on every builder:

author_network(my_df, authors = "Author Names", sep = ",")
keyword_network(my_df, keywords = "Tags",       sep = ",")

The work identifier is the id column. You need not supply one: when no id column is present each row is treated as one document; pass id = "paper_id" to use a differently-named column. Surrounding quotes are stripped by default (strip_quotes = TRUE), and in a coupling network the references column takes its own references_sep. The companion vignette("reading-data") covers every reader and these options in full.

The standard schema

Readers return a common set of columns:

data(scopus_quantum_cloud)
sc <- scopus_quantum_cloud
names(sc)[1:12]
#>  [1] "id"             "title"          "year"           "journal"       
#>  [5] "doi"            "cited_by_count" "abstract"       "type"          
#>  [9] "authors"        "references"     "keywords"       "affiliations"

The columns that matter for network construction are id, the list-columns authors / references / keywords, and year (used by temporal_network()). Source-specific extras such as countries, affiliations, and keywords_plus are kept when available.

Datasets used here

data(biblio_data)
data(learning_analytics)

small <- biblio_data            # tiny, synthetic
oa    <- learning_analytics     # 1,508 OpenAlex records on learning analytics

c(small = nrow(small), scopus = nrow(sc), openalex = nrow(oa))
#>    small   scopus openalex 
#>       10      499     1508

Author collaboration

Two authors are linked when they appear on the same paper:

authors <- author_network(oa, type = "collaboration")
head(authors, 5)
#> # bibnets network: author_collaboration | 9 nodes · 5 edges | counting: full 
#>    from                        to                          weight  count
#> 1  MOHAMMED SAQR               SONSOLES LÓPEZ‐PERNAS        19     19
#> 2  CRISTIAN CECHINEL           ROBERTO MUÑOZ                  11     11
#> 3  DRAGAN GAŠEVIĆ            ROBERTO MARTÍNEZ‐MALDONADO      10     10
#> 4  ROBERTO MARTÍNEZ‐MALDONADO  VANESSA ECHEVERRÍA             10     10
#> 5  FERNANDA PIRES              MARCELA PESSOA                   8      8
summary(authors)
#> bibnets network
#> ------------------------------
#> Type       : author_collaboration
#> Counting   : full
#> Similarity : none
#> Nodes      : 4029
#> Edges      : 12270
#> Density    : 0.0015
#> Weight     : min 1  median 1  max 19
#> Top nodes  : DRAGAN GAŠEVIĆ(89), ARI KORHONEN(60), CLAUDIA SZABO(60), JUDY SHEARD(60), PAUL DENNY(56)

Use min_occur to drop rare authors before projection:

nrow(author_network(oa, type = "collaboration"))
#> [1] 12270
nrow(author_network(oa, type = "collaboration", min_occur = 2))
#> [1] 1362

Counting methods

counting controls how much each paper contributes to an edge:

head(author_network(small, type = "collaboration", counting = "full"), 3)
#> # bibnets network: author_collaboration | 4 nodes · 3 edges | counting: full 
#>    from     to       weight  count
#> 1  CHEN W   LEE K         3      3
#> 2  BROWN M  SMITH J       3      3
#> 3  BROWN M  LEE K         2      2
head(author_network(small, type = "collaboration", counting = "fractional"), 3)
#> # bibnets network: author_collaboration | 5 nodes · 3 edges | counting: fractional 
#>    from     to       weight  count
#> 1  CHEN W   LEE K         2      3
#> 2  BROWN M  SMITH J       2      3
#> 3  JONES A  SMITH J     1.5      2
head(author_network(small, type = "collaboration", counting = "harmonic"), 3)
#> # bibnets network: author_collaboration | 5 nodes · 3 edges | counting: harmonic 
#>    from     to       weight  count
#> 1  BROWN M  SMITH J  0.4702      3
#> 2  JONES A  SMITH J   0.371      2
#> 3  CHEN W   LEE K    0.3214      3
head(author_network(small, type = "collaboration", counting = "first_last"), 3)
#> # bibnets network: author_collaboration | 5 nodes · 3 edges | counting: first_last 
#>    from     to       weight  count
#> 1  BROWN M  SMITH J    0.49      3
#> 2  CHEN W   LEE K      0.41      3
#> 3  JONES A  SMITH J    0.33      2

The available methods differ in how they weight the rows or positions before projection:

Method What it does Trade-off When to use
"full" Leaves the binary incidence matrix unchanged; for positional author weights, every listed entity receives weight 1. Large teams or long lists create many full-strength pairs. Use for raw event counts where every observed co-occurrence should count equally.
"fractional" For symmetric networks, each row contributes 1 / (n - 1) to pairs when n > 1; for coupling it uses 1 / n; positional use gives each entity 1 / n. Reduces large-list dominance but treats all positions equally. Use when each paper or reference list should have limited influence and position is not meaningful.
"paper" For symmetric networks, each paper’s pair budget is scaled by 2 / (n * (n - 1)); for coupling it uses 1 / n. Normalizes at the paper level, so very large and very small papers can contribute comparable total pair mass. Use when publications, rather than individual author/entity pairs, should be the main unit of contribution.
"strength" Multiplies entity columns by the square root of inverse document frequency, sqrt(log(n_works / entity_frequency)); row-size scaling for coupling is deferred to projection. Downweights ubiquitous entities and emphasizes rarer shared entities; values are less like direct counts. Use for coupling or profile similarity where common references, keywords, or entities should carry less evidence.
"harmonic" Uses positional weights proportional to 1 / position, normalized to sum to one. Strongly favors early positions while still giving every later position some credit. Use when author order matters and early authorship should dominate without excluding later authors.
"arithmetic" Uses a linear decline from first to last, proportional to n - position + 1, normalized. Gives a gentler first-author advantage than geometric methods. Use when byline order matters but credit should decrease steadily rather than sharply.
"geometric" Uses weights proportional to 0.5^(position - 1), normalized. Concentrates credit heavily at the front of the byline. Use when the first few positions are expected to carry most of the contribution.
"adaptive_geometric" Uses a geometric sequence normalized so the first-to-last weight ratio equals n (2/3, 1/3 for two authors). Adapts the steepness to team size, making long bylines more front-loaded. Use when first-author emphasis should increase with the number of authors.
"golden" Uses golden-ratio decay, proportional to phi^(n - position), normalized. More front-loaded than arithmetic but less abrupt than fixed halving. Use as a moderate positional decay when author order matters but geometric halving is too strong.
"first" Gives weight 1 to the first position and 0 to all others. Ignores all non-first contributors. Use for strict first-author analyses.
"last" Gives weight 1 to the last position and 0 to all others. Ignores all non-last contributors. Use where last authorship represents the analytical role of interest, such as senior or PI credit.
"first_last" With two authors, assigns 0.5 and 0.5; otherwise gives first and last authors an elevated weight and middle authors a baseline weight, all normalized. Highlights both endpoints while still retaining middle-author credit. Use in fields where first and last positions have distinct credit or leadership meanings.
"position_weighted" Uses the supplied position_weights vector, extending the last value to longer bylines, then normalizes. Puts the burden of choosing defensible weights on the analyst. Use when you have field-specific or study-specific positional weights.

Attention weights

Standard bibliometric co-authorship networks treat every byline position as equivalent: a first author who conceived and drove the work is weighted identically to a fifteenth contributor who provided a single instrument reading. On hyper-authored papers this produces dense, low-meaning co-authorship ties that drown out the focused two- or three-author collaborations that often signal the sharpest intellectual kinship. The attention weighting feature in bibnets is designed to correct this. The name is an honest analogy to the attention mechanism in large language models: just as a transformer assigns a normalized probability distribution across the tokens in a sequence — concentrating weight on what matters, spreading it thin over the rest — bibnets assigns each author on a paper a positional weight that sums to one across the full byline. A fifty-author paper therefore contributes exactly one unit of connection budget, the same as a two-author paper, and the distribution of that budget reflects authorship conventions: "lead" concentrates weight on the first author, "last" on the senior or PI position, "proximity" rewards the central authors, and "circular" rewards both ends jointly. The weights are a fixed positional prior, not learned content-based attention, but they carry real scholarly meaning, and activating them requires nothing more than passing attention = "lead" (or any of the three alternatives) to any of the author, keyword, country, or institution network functions.

attention Weight vector Scholarly assumption When it fits
"lead" Quadratic drop from the first position: the first position has raw weight n^2, inner positions decline as the byline advances, and the last position has raw weight 1, then all weights are normalized. The lead author is the main intellectual driver. Use in first-author-oriented fields or questions about lead contribution.
"last" Quadratic rise to the last position: the first position has raw weight 1, inner positions rise across the byline, and the last position has raw weight n^2, then all weights are normalized. The last author represents senior, supervisory, or PI contribution. Use in disciplines where last authorship marks lab leadership or supervision.
"proximity" Pyramid profile using min(position, n + 1 - position): first and last positions have raw weight 1, inner positions increase toward the middle, and central positions are highest. Central byline positions deserve the most attention. Use when the question treats middle-position contributors as the focal group.
"circular" Edge profile using max(position, n + 1 - position): first and last positions have the largest raw weight, while inner positions decline toward the center. Both ends of the byline are prominent. Use where lead and senior positions jointly matter more than middle positions.

attention applies a smooth positional profile instead of a named counting scheme (available for author, keyword, country, and institution networks):

head(author_network(small, attention = "lead"), 3)
#> # bibnets network: author_attention_lead | 4 nodes · 3 edges | counting: lead 
#>    from     to       weight  count
#> 1  BROWN M  SMITH J  0.3896      3
#> 2  JONES A  SMITH J  0.3437      2
#> 3  JONES A  LEE K    0.2041      2

Reference co-citation

Two references are linked when a paper cites both:

refs <- reference_network(sc, min_occur = 2)
head(refs, 5)
#> # bibnets network: reference_co_citation | 7 nodes · 5 edges | counting: full 
#>    from                            to                              weight  count
#> 1  HE K., ZHANG X., REN S., SUN …  SIMONYAN K., ZISSERMAN A., VE…      10     10
#> 2  HE K., ZHANG X., REN S., SUN …  SANDLER M., HOWARD A., ZHU M.…       8      8
#> 3  HAN S., MAO H., DALLY W.J., D…  SIMONYAN K., ZISSERMAN A., VE…       8      8
#> 4  HE K., ZHANG X., REN S., SUN …  SIMONYAN K., ZISSERMAN A., VE…       8      8
#> 5  KRIZHEVSKY A., HINTON G., LEA…  SIMONYAN K., ZISSERMAN A., VE…       7      7

A similarity measure offsets the advantage of very frequently cited works:

head(reference_network(sc, min_occur = 2, similarity = "cosine"), 3)
#> # bibnets network: reference_co_citation | 6 nodes · 3 edges | counting: full | similarity: cosine 
#>    from                            to                              weight  count
#> 1  ANDRI R., CAVIGELLI L., ROSSI…  CAPOTONDI A., RUSCI M., FARIS…       1      2
#> 2  BAI Y., ZENG B., LI C., ZHANG…  CASTELLI M., CLEMENTE F.M., P…       1      2
#> 3  CHEN K., ET AL., A DNN OPTIMI…  CHEN Y., ET AL., SAMBA: SINGL…       1      2

Document coupling and citation

Coupling links two documents that share cited references:

head(document_network(sc, type = "coupling", similarity = "cosine"), 5)
#> # bibnets network: document_coupling | 10 nodes · 5 edges | counting: full | similarity: cosine 
#>    from                to                  weight  count
#> 1  2-s2.0-85169545148  2-s2.0-85150169631  0.4671     12
#> 2  2-s2.0-85203687776  2-s2.0-85200587918  0.3872     10
#> 3  2-s2.0-85131677679  2-s2.0-85172072697  0.3424      7
#> 4  2-s2.0-85187392673  2-s2.0-85124224751   0.269     11
#> 5  2-s2.0-85161914543  2-s2.0-85100337829  0.2443     13

Direct citation is directed — from cites to — and only within the corpus (the cited work must also be a row in the data):

head(document_network(sc, type = "citation"), 5)
#> # bibnets network: document_citation | 0 nodes · 0 edges | counting: full

Keyword co-occurrence

kw <- keyword_network(sc, min_occur = 2)
head(kw, 5)
#> # bibnets network: keyword_co_occurrence | 5 nodes · 5 edges | counting: full 
#>    from            to              weight  count
#> 1  EDGE COMPUTING  QUANTIZATION        16     16
#> 2  DEEP LEARNING   QUANTIZATION        14     14
#> 3  DEEP LEARNING   EDGE COMPUTING      13     13
#> 4  DEEP LEARNING   FPGA                10     10
#> 5  PRUNING         QUANTIZATION        10     10

Labels are trimmed and upper-cased during construction, so machine learning, Machine Learning, and MACHINE LEARNING are one node. Association strength is a common choice for co-occurrence maps:

head(keyword_network(sc, min_occur = 2, similarity = "association"), 3)
#> # bibnets network: keyword_co_occurrence | 6 nodes · 3 edges | counting: full | similarity: association 
#>    from                    to                          weight  count
#> 1  AIR QUALITY PREDICTION  POST-TRAINING QUANTISATION     0.5      2
#> 2  LFSR SEED               QUANTIZATION (SIGNAL)          0.5      2
#> 3  BOOTH MULTIPLIERS       SHIFT MULTIPLIERS              0.5      2

Countries, institutions, and sources

head(country_network(oa, counting = "fractional"), 5)
#> # bibnets network: country_collaboration | 8 nodes · 5 edges | counting: fractional 
#>    from  to  weight  count
#> 1  BR    CL     9.7     11
#> 2  CA    US     9.5     13
#> 3  AU    US   8.967     15
#> 4  DE    NL   8.311     10
#> 5  CN    US     8.2     11
head(institution_network(oa, counting = "fractional", min_occur = 2), 5)
#> # bibnets network: institution_collaboration | 10 nodes · 5 edges | counting: fractional 
#>    from                            to                             weight  count
#> 1  FINLAND UNIVERSITY              UNIVERSITY OF EASTERN FINLAND   5.778     13
#> 2  MAASTRICHT SCHOOL OF MANAGEME…  MAASTRICHT UNIVERSITY           4.833      6
#> 3  ESCUELA SUPERIOR POLITECNICA …  MONASH UNIVERSITY               4.667      6
#> 4  UNIVERSIDADE FEDERAL DE SANTA…  UNIVERSITY OF VALPARAÍSO       4.417     10
#> 5  KUMAMOTO UNIVERSITY             KYUSHU UNIVERSITY                   4      4
head(source_network(sc, type = "coupling", min_occur = 2), 5)
#> # bibnets network: source_coupling | 5 nodes · 5 edges | counting: full 
#>    from                            to                              weight  count
#> 1  IEEE TRANSACTIONS ON CIRCUITS…  IEEE TRANSACTIONS ON COMPUTER…      48     48
#> 2  IEEE TRANSACTIONS ON CIRCUITS…  PROCEEDINGS OF THE IEEE             40     40
#> 3  IEEE TRANSACTIONS ON CIRCUITS…  IEEE TRANSACTIONS ON VERY LAR…      39     39
#> 4  IEEE JOURNAL OF SOLID-STATE C…  IEEE TRANSACTIONS ON CIRCUITS…      31     31
#> 5  IEEE TRANSACTIONS ON COMPUTER…  IEEE TRANSACTIONS ON VERY LAR…      29     29

For coupling networks, min_occur is applied to the aggregated entity before the network is built.

Generic co-networks

conetwork() covers projections without a dedicated wrapper. One field links entities that co-occur; a second field (by) links them through a shared value:

head(conetwork(sc, "keywords", min_occur = 2), 3)
#> # bibnets network: keywords_co_occurrence | 3 nodes · 3 edges | counting: full 
#>    from            to              weight  count
#> 1  EDGE COMPUTING  QUANTIZATION        16     16
#> 2  DEEP LEARNING   QUANTIZATION        14     14
#> 3  DEEP LEARNING   EDGE COMPUTING      13     13
head(conetwork(sc, "authors", by = "keywords", min_occur = 2), 3)
#> # bibnets network: authors_by_keywords | 6 nodes · 3 edges | counting: full 
#>    from       to                 weight  count
#> 1  CAI H      LIU B                  36     36
#> 2  WANG Y     YIN S                  30     30
#> 3  AMROUCH H  ANAGNOSTOPOULOS I      24     24

The second result links authors through shared keywords — a thematic similarity network, not a co-authorship one.

Normalization

The same raw counts support different similarity scores; only weight changes, count does not:

none <- keyword_network(sc, min_occur = 2, similarity = "none")
cos  <- keyword_network(sc, min_occur = 2, similarity = "cosine")
head(none[, c("from", "to", "weight", "count")], 3)
#> # bibnets network: unknown | 3 nodes · 3 edges 
#>    from            to              weight  count
#> 1  EDGE COMPUTING  QUANTIZATION        16     16
#> 2  DEEP LEARNING   QUANTIZATION        14     14
#> 3  DEEP LEARNING   EDGE COMPUTING      13     13
head(cos[,  c("from", "to", "weight", "count")], 3)
#> # bibnets network: unknown | 6 nodes · 3 edges 
#>    from                    to                          weight  count
#> 1  AIR QUALITY PREDICTION  POST-TRAINING QUANTISATION       1      2
#> 2  LFSR SEED               QUANTIZATION (SIGNAL)            1      2
#> 3  BOOTH MULTIPLIERS       SHIFT MULTIPLIERS                1      2

normalize() uses the diagonal of the projected matrix as each node’s total occurrence count:

Similarity Denominator Meaning When to use
"none" No denominator; the projected matrix is returned as raw weighted co-occurrence, with the diagonal removed by the network builder unless self-loops are requested. weight stays on the same scale as the counted projection. Use when absolute co-occurrence or counted edge strength is the quantity of interest.
"cosine" Square root of the product of the two node totals. Symmetric size correction; pairs are high when their overlap is large relative to both nodes’ frequencies. Use as a general-purpose correction for very frequent nodes while preserving a familiar similarity scale.
"association" Product of the two node totals. Symmetric association-strength normalization; strongly penalizes pairs involving very frequent nodes. Use for co-occurrence maps where you want rare, unexpectedly tight pairings to stand out.
"jaccard" Sum of the two node totals minus their observed edge value. Symmetric overlap over a union-like total. Use when the edge should represent shared occurrence as a share of either node’s combined footprint.
"inclusion" The smaller of the two node totals. Symmetric containment-oriented score; it reaches high values when the smaller node mostly appears with the larger one. Use when subset or specialization relationships are more important than balanced overlap.
"equivalence" Product of the two node totals, with the edge value squared before division. Cosine-like normalization with stronger penalty for weak or occasional overlap. Use when following equivalence-index conventions or when only consistently paired nodes should remain strong.

Reducing large networks

edges <- author_network(oa, type = "collaboration")
c(all        = nrow(edges),
  threshold  = nrow(prune(edges, threshold = 2)),
  top_n      = nrow(prune(edges, top_n = 5)),
  top_nodes  = nrow(filter_top(edges, n = 50)))
#>       all threshold     top_n top_nodes 
#>     12270       779     12188       956

backbone() applies the disparity filter, which keeps edges that are strong relative to a node’s local strength distribution — not a global cutoff:

bb <- backbone(edges, alpha = 0.05)
nrow(bb)
#> [1] 232

Temporal networks

temporal_network() runs any builder over time windows (fixed, sliding, or cumulative):

tn <- temporal_network(oa, author_network, "collaboration", window = 3)
names(tn)
#> [1] "2011-2013" "2014-2016" "2017-2019" "2020-2022" "2023-2025" "2026-2026"

Each window’s edge list carries a window column. Windows with fewer than two records, or no surviving edges, are dropped; a builder error inside a window becomes a warning labelled with that window.

Local citations and historiographs

local_citations() counts how often each document is cited by others in the same corpus; historiograph() builds the directed citation graph among the top-cited documents:

head(local_citations(sc), 5)
#>                    id lcs gcs year
#> 1 2-s2.0-105007159281   0   0 2025
#> 2 2-s2.0-105006878874   0   0 2025
#> 3  2-s2.0-85211114952   0   0 2024
#> 4 2-s2.0-105001072133   0   0 2025
#> 5  2-s2.0-85210832535   0   5 2025
#>                                                                                                                                  title
#> 1                                          Quantum Computing in the RAN with Qu4Fec: Closing Gaps Towards Quantum-based FEC Processors
#> 2                                                An FPGA-based bit-level weight sparsity and mixed-bit accelerator for neural networks
#> 3                             FQP: A Fibonacci Quantization Processor with Multiplication-Free Computing and Topological-Order Routing
#> 4                                                   SysCIM: A Heterogeneous Chip Architecture for High-Efficiency CNN Training at Edge
#> 5 Integer-Valued Training and Spike-Driven Inference Spiking Neural Network for High-Performance and Energy-Efficient Object Detection
#>                                                                                                                                 journal
#> 1                                                               Proceedings of the ACM on Measurement and Analysis of Computing Systems
#> 2                                                                                                       Journal of Systems Architecture
#> 3                                                                                            Proceedings - Design Automation Conference
#> 4                                                                      IEEE Transactions on Very Large Scale Integration (VLSI) Systems
#> 5 Lecture Notes in Computer Science (including subseries Lecture Notes in Artificial Intelligence and Lecture Notes in Bioinformatics) 
#>                            doi
#> 1              10.1145/3727128
#> 2 10.1016/j.sysarc.2025.103463
#> 3      10.1145/3649329.3656502
#> 4   10.1109/TVLSI.2025.3526363
#> 5 10.1007/978-3-031-73411-3_15

h <- historiograph(sc, n = 10)
h$nodes
#> [1] id      lcs     gcs     year    title   journal doi    
#> <0 rows> (or 0-length row.names)
head(h$edges, 5)
#> [1] from      to        year_from year_to  
#> <0 rows> (or 0-length row.names)

Both require reference strings or IDs to match document IDs in the data; if the cited works are external, local counts stay low.

Author-name normalization

parse_names() reorders and splits author names (it recognizes Last, First, SURNAME Initials, and First Last). Because node identity is fixed when a network is built, normalize before building so that two spellings of one author merge:

parse_names(c("Saqr, Mohammed", "WANG Y", "Mohammed Saqr"))
#> [1] "Mohammed Saqr" "Y WANG"        "Mohammed Saqr"
#> attr(,"parts")
#>         original    first last particle suffix   type
#> 1 Saqr, Mohammed Mohammed Saqr     <NA>   <NA> person
#> 2         WANG Y        Y WANG     <NA>   <NA> person
#> 3  Mohammed Saqr Mohammed Saqr     <NA>   <NA> person

See vignette("parsing-author-names") for the full treatment.

Exporting

The edge list is already usable; converters cover the common targets:

edges <- keyword_network(sc, min_occur = 2)

m <- to_matrix(edges)            # sparse adjacency matrix
m[1:4, 1:4]
#> 4 x 4 sparse Matrix of class "dgCMatrix"
#>                ACCELERATION ACCELERATOR ACCURACY AI ACCELERATOR
#> ACCELERATION              .           .        .              .
#> ACCELERATOR               .           .        .              .
#> ACCURACY                  .           .        .              .
#> AI ACCELERATOR            .           .        .              .

gephi <- to_gephi(edges)         # Gephi node/edge tables
head(gephi$edges, 3)
#>           Source         Target Weight       Type count
#> 1 EDGE COMPUTING   QUANTIZATION     16 Undirected    16
#> 2  DEEP LEARNING   QUANTIZATION     14 Undirected    14
#> 3  DEEP LEARNING EDGE COMPUTING     13 Undirected    13

cat(substr(to_graphml(edges), 1, 200))   # GraphML, no XML dependency
#> <?xml version="1.0" encoding="UTF-8"?>
#> <graphml xmlns="http://graphml.graphdrawing.org/graphml"
#>          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
#>          xsi:schemaLocation="http://graph

to_igraph(), to_tbl_graph(), and to_cograph() are available when their (suggested) packages are installed.

Reading a bibnets_network

The object records how it was built, as attributes:

edges <- author_network(oa, type = "collaboration", counting = "harmonic")
c(type     = attr(edges, "network_type"),
  counting = attr(edges, "counting"),
  sim      = attr(edges, "similarity"))
#>                   type               counting                    sim 
#> "author_collaboration"             "harmonic"                 "none"

summary(edges)
#> bibnets network
#> ------------------------------
#> Type       : author_collaboration
#> Counting   : harmonic
#> Similarity : none
#> Nodes      : 4029
#> Edges      : 12270
#> Density    : 0.0015
#> Weight     : min 1.43e-05  median 0.0106  max 1.41
#> Top nodes  : DRAGAN GAŠEVIĆ(89), ARI KORHONEN(60), CLAUDIA SZABO(60), JUDY SHEARD(60), PAUL DENNY(56)

print() reports the network type, node and edge counts, and the counting and similarity methods — so a saved edge list always says how it was made.

References

The methodology implemented in bibnets is described in:

López-Pernas, S., Saqr, M., & Apiola, M. (2023). Scientometrics: A Concise Introduction and a Detailed Methodology for Mapping the Scientific Field of Computing Education Research. In M. Apiola, S. López-Pernas, & M. Saqr (Eds.), Past, Present and Future of Computing Education Research: A Global Perspective (pp. 79–99). Springer Nature Switzerland AG. https://doi.org/10.1007/978-3-031-25336-2_5

Saqr, M., López-Pernas, S., Conde, M. Á., & Hernández-García, Á. (2024). Social Network Analysis: A primer, a guide and a tutorial in R. In M. Saqr & S. López-Pernas (Eds.), Learning Analytics Methods and Tutorials: A Practical Guide Using R (pp. 491–518). Springer, Cham. https://doi.org/10.1007/978-3-031-54464-4_15