Parsing and normalising author names

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(bibnets)

What parse_names() is

parse_names() is an optional, standalone utility for cleaning author name strings. It does two things:

  1. Reorders names to "First Last" (or other styles).
  2. Breaks each name into components (first, last, particle, suffix), returned as the "parts" attribute.

It is not called by any reader or network builder. bibnets matches entity labels verbatim; you opt in to normalisation by calling this function yourself.

parse_names(c("Saqr, Mohammed", "Lopez-Pernas, Sonsoles"))

The three name conventions

Bibliometric exports use three incompatible conventions. parse_names() recognises all three; the rule is decided per string.

| Input | Convention | Detected by | |---|---|---| | "Saqr, Mohammed" | Last, First | the comma | | "WANG Y" | SURNAME Initials (Scopus/bibnets) | trailing uppercase 1–3 letter token | | "Mohammed Saqr" | First Last | default for comma-less, non-initial |

parse_names(c("Saqr, Mohammed", "WANG Y", "Mohammed Saqr"))

A comma always means Last, First. For comma-less strings the surname_first argument controls interpretation:

parse_names("Wang Yong", surname_first = "yes")   # force surname-first
parse_names("WANG Y",    surname_first = "no")    # force given-first

Particles and suffixes are handled, and detection is case-insensitive so it works on bibnets' upper-cased labels:

parse_names(c("van der Berg, Jan", "Smith, John, Jr.",
              "DE LA CRUZ, ANA", "VAN DER BERG J"))

Group / corporate authors, NA, and empty strings are left untouched:

parse_names(c("WHO Collaborating Group", NA, ""))

Output styles: format

nm <- c("Saqr, Mohammed", "van der Berg, Jan", "Garcia Marquez, Gabriel Jose")
data.frame(
  first_last    = parse_names(nm),
  last_initials = parse_names(nm, format = "last_initials"),
  last          = parse_names(nm, format = "last")
)

The "parts" attribute

The parsed components ride along on every call, independent of format:

x <- parse_names(c("van der Berg, Jan", "Smith, John, Jr."))
attr(x, "parts")

type is one of "person", "organization", "empty", "missing".

Input shape: vector, not data frame

parse_names() works on one flat character vector. It is not a data-frame function.

bibnets readers store authors as a list-column: each paper has a variable number of authors, so the cell holds a vector, not a single string.

papers <- data.frame(id = c("P1", "P2", "P3"), stringsAsFactors = FALSE)
papers$authors <- list(
  c("Saqr, Mohammed", "Lopez, Ana"),
  c("SAQR M",         "Lopez, Ana"),
  c("Saqr, Mohammed", "Chen, Wei"))
papers$authors

Map the function over the list-column with lapply():

papers$authors <- lapply(papers$authors, parse_names,
                          format = "last_initials")
papers$authors

A flat character column (or a network's from / to) is called directly, no lapply():

parse_names(c("WANG Y", "AYALA-ROMERO JA"))

Recommended workflow: normalise before building

Node identity in bibnets is fixed when the network is built (labels are upper-cased and matched verbatim). Two spellings of one author merge into a single node only if normalised before author_network().

Here "Saqr, Mohammed" and "SAQR M" are the same person written two ways. After normalising they both become SAQR M., so the Saqr–Lopez collaboration is correctly counted as 2:

net <- author_network(papers, type = "collaboration")
net

Had we built the network first and called parse_names() on from / to afterwards, the two spellings would already have been counted as two separate nodes — too late to merge by relabelling.

Applying to an existing edgelist (and its hazards)

The network object is a data frame (from, to, weight, count) with an extra bibnets_network class for printing:

class(net)
is.data.frame(net)

You can relabel from / to directly, but parse_names() is graph-blind. Edges, pairing, weight and count are preserved, but:

net$from <- as.vector(parse_names(net$from, format = "last"))
net$to   <- as.vector(parse_names(net$to,   format = "last"))
net

Use as.vector() when assigning back so the "parts" attribute is not carried on the column.

Limitations

Summary



Try the bibnets package in your browser

Any scripts or data that you put into this service are public.

bibnets documentation built on June 19, 2026, 1:06 a.m.