5  Function reference

Every exported function, grouped the same way as the README. Each entry gives the signature, every argument, the return value, and at least one runnable example. This chapter is the detailed reference; Chapter 2 is the faster tour.

5.1 Matching & substitution

fgrepl()

Equivalent to base::grepl(), using PCRE2 and Intel TBB. Large inputs can use multiple cores; the crossover depends on subject length and pattern cost. See Chapter 3 for the automatic PCRE-only-syntax fallback to base::grepl(perl = TRUE). With fixed = TRUE, the byte-oriented pattern is prepared once: one-byte needles use memchr, two- and three-byte needles use memchr plus memcmp, and longer needles use Boyer–Moore–Horspool. ignore.case = TRUE uses a 256-entry byte-folding table without lowercasing each input string.

fgrepl(pattern, x, ignore.case = FALSE, perl = FALSE,
       fixed = FALSE, useBytes = FALSE, nthreads = NULL)
Argument Description
pattern Character scalar. Pattern to search for.
x Character vector. NA elements return NA.
ignore.case Logical. Case-insensitive matching.
perl Logical. If TRUE, skip the PCRE-only syntax check and run the parallel PCRE2 engine directly.
fixed Logical. Treat pattern as bytes and use the prepared literal-search path.
useBytes Logical. Ignored; kept for signature compatibility with base::grepl().
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.

Returns: logical vector the same length as x.

fgrepl("^inv", c("invoice", "Invoice", "credit"), ignore.case = TRUE)
[1]  TRUE  TRUE FALSE
fgrepl("a.b", c("axb", "ab"), fixed = TRUE)  # literal "a.b" — no match for "axb"
[1] FALSE FALSE

fgrep()

Equivalent to base::grep(): wraps fgrepl() and returns indices or values.

fgrep(pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE,
      fixed = FALSE, useBytes = FALSE, invert = FALSE, nthreads = NULL)
Argument Description
pattern, x, ignore.case, perl, fixed, useBytes, nthreads Same as fgrepl().
value Logical. Return matching elements instead of indices.
invert Logical. Return non-matching indices/values instead.

Returns: integer vector of indices, or a character vector when value = TRUE.

fgrep("^inv", c("invoice", "credit", "invoice2"))
[1] 1 3
fgrep("^inv", c("invoice", "credit", "invoice2"), value = TRUE)
[1] "invoice"  "invoice2"

fcount()

No direct base R equivalent (the usual idiom is vapply(gregexpr(...), length, ...), which allocates a match-position vector per element just to take its length). Counts non-overlapping matches of one pattern in each element, using the same PCRE2 and prepared-fixed-string engines and the same parallel dispatch as fgrepl().

fcount(pattern, x, ignore.case = FALSE, perl = FALSE,
       fixed = FALSE, useBytes = FALSE, nthreads = NULL)
Argument Description
pattern, x, ignore.case, perl, fixed, useBytes, nthreads Same as fgrepl().

Returns: integer vector the same length as x, with names(x) preserved. NA elements return NA; elements with no match return 0L.

Two cases delegate to base::gregexpr() for exactness rather than taking the fast path: an empty pattern (which has character-position semantics in base R, whereas the fixed engine works on bytes), and a pattern using PCRE-only syntax without perl = TRUE (which emits a message first, the same fallback fgrepl() uses — see Chapter 3).

fcount("[0-9]", c("a1b2c3", "none", NA))
[1]  3  0 NA
fcount("aa", "aaaa", fixed = TRUE)   # 2 -- matches do not overlap
[1] 2
# Column-level data-quality rules, one vectorised call each
nm <- c("JOHN O'BRIEN", "UNKNOWN 00000000", "Kyle John Haynes")
fcount("[0-9]", nm)        # digits in a name field
[1] 0 8 0
fcount(" +", nm) + 1L      # token count
[1] 2 2 3

fsub()

Equivalent to base::sub(): first-match substitution. Supports \\1-\\9 capture groups and \\U/\\L/\\E case conversion in replacement.

fsub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,
     fixed = FALSE, useBytes = FALSE, nthreads = NULL)
Argument Description
pattern Character scalar. Pattern to search for.
replacement Character scalar. Replacement string.
x Character vector. NA elements return NA.
ignore.case, perl, fixed, useBytes, nthreads Same as fgrepl().

Returns: character vector the same length as x.

fsub("-([0-9]+)$", "_\\1", c("invoice-001", "invoice-002"))
[1] "invoice_001" "invoice_002"

fgsub()

Equivalent to base::gsub(): global substitution. Same capture-group and case-conversion support as fsub().

fgsub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,
      fixed = FALSE, useBytes = FALSE, nthreads = NULL)

Arguments are identical to fsub(). Returns: character vector the same length as x.

fgsub("[aeiou]", "_", c("hello world", "fast string"), ignore.case = TRUE)
[1] "h_ll_ w_rld" "f_st str_ng"

gsub_all()

No base R equivalent: applies several patterns in a single function call, either sequentially (chained, like repeated fgsub() calls — later patterns can match text introduced by earlier replacements) or, for fixed = TRUE, as one combined left-to-right scan (sequential = FALSE). Non-sequential regex replacement is rejected explicitly.

gsub_all(patterns, replacements, x, fixed = FALSE, ignore.case = FALSE,
          sequential = TRUE, nthreads = NULL)
Argument Description
patterns Character vector of patterns to search for.
replacements Character scalar or vector the same length as patterns.
x Character vector. NA elements return NA.
fixed Logical. Treat each pattern as a literal string.
ignore.case Logical. Case-insensitive matching.
sequential Logical (default TRUE). TRUE = chained passes; FALSE = fixed-pattern single combined scan.
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.

Returns: character vector the same length as x.

gsub_all(c("Mr\\.", "Mrs\\."), c("Mister", "Missus"), c("Mr. Smith", "Mrs. Jones"))
[1] "Mister Smith" "Missus Jones"

5.2 String utilities

All four functions in this group preserve names(x) and NA handling exactly like their base R equivalents.

ftrimws()

ftrimws(x, which = c("both", "left", "right"), whitespace = "[ \t\r\n]")
Argument Description
x Character vector. NA elements return NA.
which One of "both", "left", "right".
whitespace Regex of characters to strip. Only the default "[ \t\r\n]" uses the fast path; any other value delegates to base::trimws().

Returns: character vector the same length as x, with names(x) preserved.

ftrimws(c("  padded  ", "\ttabbed\n"))
[1] "padded" "tabbed"
ftrimws("  left only", which = "left")
[1] "left only"

fsubstr()

fsubstr(x, start, stop)
Argument Description
x Character vector. NA elements return NA.
start, stop Integer (or numeric) vectors of length 1 or length(x), 1-indexed, clamped to each string’s bounds, recycled to length(x). NA in either produces NA for that element.

Returns: character vector the same length as x.

fsubstr("NSWREC123456789", 1, 3)
[1] "NSW"
fsubstr(rep("ABCDEFGH", 3), c(1, 4, 7), c(3, 6, 8))  # vectorised start/stop
[1] "ABC" "DEF" "GH" 

fnchar()

fnchar(x, type = "chars", allowNA = FALSE, keepNA = NA)
Argument Description
x Vector, coerced to character via as.character() if needed.
type One of "bytes", "chars", or "width". "width" delegates to base::nchar() (display width isn’t parallelised).
allowNA Logical. Ignored; the fast path never raises an encoding error regardless.
keepNA Logical or NA (default). NA/TRUE: NA elements of x return NA. FALSE: they return 2L (length of the string "NA"), matching base R’s legacy behaviour.

Returns: integer vector the same length as x, with names(x) preserved.

fnchar(c("café", "abc", NA))
[1]  4  3 NA
fnchar(c("café", "abc"), type = "bytes")  # "é" is 2 bytes in UTF-8
[1] 5 3

fchartr()

fchartr(old, new, x)
Argument Description
old, new Single strings with the same number of characters. Each character of old maps to the corresponding character of new.
x Character vector. NA elements return NA.

Returns: character vector the same length as x. Falls back to base::chartr() automatically when old/new contain multi-byte characters (the fast path is a flat byte lookup table, valid only for single-byte/ASCII characters).

fchartr("'-", "  ", c("O'Brien", "Smith-Jones"))
[1] "O Brien"     "Smith Jones"
fchartr("aeiou", "AEIOU", "fast string")
[1] "fAst strIng"

5.3 Dates

format_date()

format_date(x, format = c("iso", "compact", "dmy", "ymd_slash"))
Argument Description
x A Date object or numeric vector of days since 1970-01-01.
format "iso" (YYYY-MM-DD), "compact" (YYYYMMDD), "dmy" (DD/MM/YYYY), or "ymd_slash" (YYYY/MM/DD).

Returns: character vector the same length as x.

format_date(as.Date(c("2024-06-18", NA)), "compact")
[1] "20240618" NA        

format_date_parts()

Pure string-building (zero-padding plus punctuation, no calendar math, no Date object) — the inverse of date_parts().

format_date_parts(year, month, day, format = c("iso", "compact", "dmy", "ymd_slash"))
Argument Description
year, month, day Numeric vectors, recycled to a common length. NA, non-integer-coercible, or out-of-width values (year outside 0-9999, month/day outside 0-99) produce NA for that element. No calendar validation — month = 13 formats as given if it fits the field width.
format Same four options as format_date().

Returns: character vector recycled to the common length of year, month, day.

format_date_parts(2024, 6, 18, "iso")
[1] "2024-06-18"

date_parts()

date_parts(x)
Argument Description
x A Date object or numeric vector of days since 1970-01-01.

Returns: a data.frame with integer columns year, month, day.

date_parts(as.Date(c("2024-06-18", "1999-12-31")))
  year month day
1 2024     6  18
2 1999    12  31

fas.Date()

Not a drop-in for base::as.Date() — see Chapter 3 for the speed/ strictness trade-off (no days-in-month or leap-year validation).

fas.Date(x, format = c("iso", "compact", "dmy", "ymd_slash"))
Argument Description
x Character vector. NA elements, and elements that don’t match format exactly (wrong length/separators/non-digits) or have an out-of-range month/day, become NA.
format Same four options as format_date(); x must be in exactly this one format.

Returns: a Date vector the same length as x.

fas.Date(c("18/06/2024", "31/12/1999", "not-a-date"), "dmy")
[1] "2024-06-18" "1999-12-31" NA          

fas.POSIXct()

Parses strict, locale-free timestamps directly into UTC seconds since the Unix epoch — no timezone-database consultation, no multi-format guessing. Unlike fas.Date(), calendar dates are fully validated, including month lengths and leap years.

fas.POSIXct(x, format = c("iso", "rfc3339", "compact", "iso_offset"))
Argument Description
x Character vector. NA elements, malformed values, and out-of-range or impossible calendar dates become NA.
format "iso" (YYYY-MM-DD HH:MM:SS), "rfc3339" (YYYY-MM-DDTHH:MM:SSZ), "compact" (YYYYMMDDHHMMSS), or "iso_offset" (YYYY-MM-DDTHH:MM:SS+HH:MM).

Returns: a POSIXct vector in UTC, the same length as x, with names(x) preserved.

fas.POSIXct(c("2024-06-18 09:15:00", "not a time"))
[1] "2024-06-18 09:15:00 UTC" NA                       
fas.POSIXct("2024-06-18T09:15:00Z", "rfc3339")
[1] "2024-06-18 09:15:00 UTC"
fas.POSIXct("20240618091500", "compact")
[1] "2024-06-18 09:15:00 UTC"
fas.POSIXct("2024-06-18T09:15:00+10:00", "iso_offset")  # normalised to UTC
[1] "2024-06-17 23:15:00 UTC"
fas.POSIXct("2023-02-29 08:00:00")                      # NA -- not a leap year
[1] NA

format_datetime()

The inverse: formats Unix-epoch seconds without locale or timezone-database overhead.

format_datetime(x, format = c("iso", "rfc3339", "compact", "iso_offset"),
                offset = "Z")
Argument Description
x A POSIXct object or numeric vector of seconds since 1970-01-01 00:00:00 UTC.
format The same four formats accepted by fas.POSIXct().
offset Fixed offset written by format = "iso_offset": "Z", or a signed "+HH:MM"/"-HH:MM" string. Must be "Z" for the other three formats, which are emitted in UTC.

Returns: character vector the same length as x.

"iso_offset" applies one fixed numeric offset to every element. It is not a timezone — there are no daylight-saving rules — so use base::format() with a real timezone when a series crosses a DST boundary.

stamps <- fas.POSIXct(c("2024-06-18 09:15:00", "2024-06-18 23:59:59"))
format_datetime(stamps, "rfc3339")
[1] "2024-06-18T09:15:00Z" "2024-06-18T23:59:59Z"
format_datetime(stamps, "compact")
[1] "20240618091500" "20240618235959"
format_datetime(stamps, "iso_offset", offset = "+10:00")
[1] "2024-06-18T19:15:00+10:00" "2024-06-19T09:59:59+10:00"

5.4 Phonetic blocking keys

None of these functions has a base R equivalent; all are intended as blocking keys ahead of fuzzy name matching (Chapter 3, Chapter 4).

soundex()

soundex(x)
Argument Description
x Character vector (coerced via as.character() if not already character — e.g. a factor read from CSV). NA elements, and elements with no alphabetic characters, return NA.

Returns: character vector the same length as x, with names(x) preserved; each element either NA or exactly 4 characters.

soundex(c("Robert", "Rupert", "Ashcraft"))
[1] "R163" "R163" "A261"

nysiis()

nysiis(x)
Argument Description
x Character vector (coerced via as.character() if needed). NA elements, and elements with no alphabetic characters, return NA.

Returns: character vector the same length as x, with names(x) preserved; each element either NA or up to 6 characters.

nysiis(c("Robert", "Rupert", "Ashcraft"))
[1] "RABAD"  "RAPAD"  "ASCRAF"

refined_soundex()

The US-English Refined Soundex mapping from Apache Commons Codec. Where classic soundex() discards vowels and truncates to four characters, Refined Soundex encodes vowels too and emits a code for every change in phonetic class, with no truncation — a longer, more discriminating key that produces smaller blocks.

refined_soundex(x)
Argument Description
x Character vector (coerced via as.character() if needed). NA elements, and elements with no ASCII letters, return NA.

Returns: character vector the same length as x, with names(x) preserved. Code length varies with the input and is not truncated — note that phonics::refinedSoundex() caps codes at 10 characters by default, so the two agree only once its maxCodeLen is raised (Chapter 3).

refined_soundex(c("Robert", "Rupert", "Ashcraft"))
[1] "R901096"   "R901096"   "A03039026"
# Splits a Soundex block that classic soundex() merges
data.frame(
    name    = c("Smith", "Smyth", "Schmidt", "Sandy"),
    soundex = soundex(c("Smith", "Smyth", "Schmidt", "Sandy")),
    refined = refined_soundex(c("Smith", "Smyth", "Schmidt", "Sandy"))
)
     name soundex refined
1   Smith    S530  S38060
2   Smyth    S530  S38060
3 Schmidt    S530  S30806
4   Sandy    S530  S30860

cologne()

The Cologne phonetic algorithm (Kölner Phonetik), designed for German pronunciation. Input is uppercased bytewise, umlauts are mapped to their base vowels, sharp s to SS, and remaining non-letters ignored before encoding — so German spelling variants that ASCII-only schemes split are grouped together.

cologne(x)
Argument Description
x Character vector (coerced via as.character() if needed). NA elements, and elements with no supported letters, return NA.

Returns: character vector the same length as x, with names(x) preserved; a digit string, or NA.

cologne(c("Müller-Lüdenscheidt", "Meier", "Meyer"))
[1] "65752682" "67"       "67"      
# Umlaut folding: refined_soundex() splits this pair, cologne() doesn't
data.frame(
    name    = c("Müller", "Mueller"),
    refined = refined_soundex(c("Müller", "Mueller")),
    cologne = cologne(c("Müller", "Mueller"))
)
     name refined cologne
1  Müller   M8709     657
2 Mueller  M80709     657

double_metaphone()

Two codes per word — primary and secondary — for ambiguous pronunciations. Ported from the structure of Apache Commons Codec’s Java implementation and cross-checked against its published test vectors. Unlike soundex()/nysiis(), internal whitespace/punctuation is not stripped before encoding (only the ends are trimmed and the text uppercased) — the algorithm itself keys off literal fragments like "VAN "/"SCH", including the space.

double_metaphone(x)
Argument Description
x Character vector (coerced via as.character() if needed). NA elements, and elements with no content after trimming, return NA in both columns.

Returns: a data.frame with character columns primary and secondary, each length(x) long.

double_metaphone(c("Smith", "Schmidt", "Catherine", "Kathryn"))
  primary secondary
1     SM0       XMT
2     XMT       SMT
3    K0RN      KTRN
4    K0RN      KTRN

caverphone()

Caverphone 2.0 (Caversham Project, University of Otago) — a fixed 10-character code via a chain of substring transforms, widely used in NZ/AU record linkage. Ported step-for-step from Apache Commons Codec’s Caverphone2 and cross-checked against its published test vectors, including the “enough”/“trough” duplicate-rule quirk inherited from the original 2004 specification (preserved rather than “corrected” — the point of a phonetic key is to match the standard everyone else uses).

caverphone(x)
Argument Description
x Character vector (coerced via as.character() if needed). NA elements return NA; every other input — including "" — returns a 10-character code.

Returns: character vector the same length as x, with names(x) preserved; each element either NA or exactly 10 characters.

caverphone(c("Peter", "Tedder", "Stevenson"))
[1] "PTA1111111" "TTA1111111" "STFNSN1111"

5.5 Fuzzy string similarity

jaro_winkler()

Vectorised pairwise Jaro-Winkler similarity. See Chapter 3 for the algorithm and the bit-parallel implementation.

jaro_winkler(a, b, p = 0.1, nthreads = NULL, use_bytes = TRUE)
Argument Description
a, b Equal-length character vectors.
p Prefix scaling factor (default 0.1, the standard value).
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.
use_bytes TRUE for compatibility byte comparison; FALSE for UTF-8 code points.

Returns: numeric vector of similarities in [0, 1].

jaro_winkler(c("MARTHA", "DWAYNE"), c("MARHTA", "DUANE"))
[1] 0.9611111 0.8400000
jaro_winkler("SMITH", "SMYTH", p = 0)    # no prefix bonus
[1] 0.8666667
jaro_winkler("SMITH", "SMYTH", p = 0.1)  # standard prefix bonus
[1] 0.8933333

jaro_winkler_matrix()

All-pairs Jaro-Winkler similarity — every element of a against every element of b.

jaro_winkler_matrix(a, b, p = 0.1, nthreads = NULL, use_bytes = TRUE)
Argument Description
a Character vector of length n (rows).
b Character vector of length m (columns).
p, nthreads Same as jaro_winkler().

Returns: numeric matrix of dimensions n × m.

jaro_winkler_matrix(c("JOHN SMITH", "MARY JONES"), c("JON SMYTH", "MARY JONES", "JOHN SMITH"))
          [,1]      [,2]      [,3]
[1,] 0.9170370 0.4222222 1.0000000
[2,] 0.3074074 1.0000000 0.4222222

jaro_winkler_tokens()

Token-reorder- and punctuation-aware Jaro-Winkler similarity. Full mechanics in Chapter 3.

jaro_winkler_tokens(a, b, p = 0.1, ignore_case = FALSE, strip = "['’-]",
                     extra_penalty = NULL, nthreads = NULL)
Argument Description
a, b Equal-length character vectors.
p Prefix scaling factor (default 0.1).
ignore_case Logical (default FALSE). Uppercase both sides before comparing.
strip Single regex string matching punctuation to remove before tokenising, or NULL to skip. Default "['’-]" strips straight/curly apostrophes and hyphens.
extra_penalty NULL (default) or a non-negative numeric scalar. NULL: unmatched tokens dilute the average (divide by max(n_tokens_a, n_tokens_b)). A number: average over only matched tokens, then subtract extra_penalty per unmatched token (floored at 0) — 0 ignores extra tokens outright.
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.

Returns: numeric vector of similarities in [0, 1]. NA if either side of a pair is NA.

# Reordered tokens, one near-miss — rescued relative to plain jaro_winkler()
jaro_winkler_tokens("Kyle John Haynes", "John Kylie Haynes")
[1] 0.9844444
jaro_winkler("Kyle John Haynes", "John Kylie Haynes")
[1] 0.8970588
# Punctuation/spacing variants of the same name
jaro_winkler_tokens(c("OBrien", "OBrien"), c("O Brien", "O'Brien"))
[1] 1 1
# A stray extra token, penalised by default...
jaro_winkler_tokens("Kylie John ZZ Haynes", "Haynes John Kyle")
[1] 0.7383333
# ...vs. ignored outright with extra_penalty = 0
jaro_winkler_tokens("Kylie John ZZ Haynes", "Haynes John Kyle", extra_penalty = 0)
[1] 0.9844444
# ...vs. lightly discounted
jaro_winkler_tokens("Kylie John ZZ Haynes", "Haynes John Kyle", extra_penalty = 0.1)
[1] 0.8844444

5.6 Fuzzy lookup

fuzzy_match() returns the best table index for every query. fuzzy_top_n() returns a long data frame of ranked candidates. Both scan the table without allocating a full all-pairs matrix and compare UTF-8 code points by default.

fuzzy_match(x, table, method = "jaro_winkler", min_score = 0,
            max_distance = NULL, match_na = FALSE,
            nomatch = NA_integer_, nthreads = NULL, use_bytes = FALSE)
fuzzy_top_n(x, table, method = "jaro_winkler", top_n = 5L,
            min_score = 0, max_distance = NULL, match_na = FALSE,
            nthreads = NULL, use_bytes = FALSE)

Supported methods are "jaro_winkler", "levenshtein", "osa", and "damerau_levenshtein". Scores are normalized to [0, 1]; ties resolve to the earliest table position.

fuzzy_match(c("SMITH", "JONES"), c("SMYTH", "JONAS", "JONES"))
[1] 1 3
fuzzy_top_n("kitten", c("sitting", "mitten", "cat"),
            method = "levenshtein", top_n = 2)
  query_index table_index     score rank
1           1           2 0.8333333    1
2           1           1 0.5714286    2

5.7 Edit distance

The edit-distance family distinguishes OSA from unrestricted Damerau-Levenshtein and offers normalized and bounded forms. Byte comparison is the compatibility default; use_bytes = FALSE compares UTF-8 code points.

levenshtein()

levenshtein(a, b, nthreads = NULL, use_bytes = TRUE)
Argument Description
a, b Equal-length character vectors.
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.
use_bytes TRUE for encoded bytes; FALSE for UTF-8 code points.

Returns: numeric vector the same length as a (minimum number of single-character insertions/deletions/substitutions). NA if either side of a pair is NA.

levenshtein("kitten", "sitting")
[1] 3

levenshtein_matrix()

All-pairs Levenshtein distance.

levenshtein_matrix(a, b, nthreads = NULL, use_bytes = TRUE)

Returns: numeric matrix of dimensions length(a) x length(b).

levenshtein_matrix(c("kitten", "cat"), c("sitting", "bat"))
     [,1] [,2]
[1,]    3    5
[2,]    6    1

osa_distance() / osa_distance_matrix()

Adjacent transpositions cost one edit under the Optimal String Alignment restriction that no substring is edited more than once.

osa_distance(a, b, nthreads = NULL, use_bytes = TRUE)
osa_distance_matrix(a, b, nthreads = NULL, use_bytes = TRUE)

Arguments identical to levenshtein(). Returns: numeric vector the same length as a.

osa_distance("ca", "abc")  # 3
[1] 3

damerau_levenshtein() / damerau_levenshtein_matrix()

Unrestricted Damerau-Levenshtein permits a substring to participate in multiple edits and matches stringdist(method = "dl").

damerau_levenshtein(a, b, nthreads = NULL, use_bytes = TRUE)
damerau_levenshtein_matrix(a, b, nthreads = NULL, use_bytes = TRUE)
damerau_levenshtein("ca", "abc")  # 2
[1] 2

Normalized and bounded edit comparison

levenshtein_similarity(), osa_similarity(), and damerau_levenshtein_similarity() return 1 - distance/max(lengths). levenshtein_within() uses a banded dynamic program to test a raw cutoff.

levenshtein_similarity(a, b, nthreads = NULL, use_bytes = TRUE)
levenshtein_within(a, b, max_distance, nthreads = NULL, use_bytes = TRUE)

hamming()

Number of positions at which two equal-length strings differ.

hamming(a, b, nthreads = NULL, use_bytes = TRUE)

Arguments identical to levenshtein(). Returns: numeric vector the same length as a; Inf for a pair of unequal length (matching stringdist::stringdist(method = "hamming")).

hamming("karolin", "kathrin")
[1] 3
hamming("abc", "ab")  # Inf -- unequal length
[1] Inf

5.8 Q-gram similarity

jaccard_index(), dice_coefficient(), tversky_index(), and cosine_similarity() compare two strings’ overlapping length-q substrings (“q-grams”). All four share one sorted-merge pass over packed-integer q-grams without routing through stringdist’s generic R-level dispatch (Chapter 6). The first three compare q-gram sets (a repeated q-gram counts once); cosine_similarity() compares frequency profiles, so repetition carries weight.

jaccard_index()

jaccard_index(a, b, q = 2, nthreads = NULL)
Argument Description
a, b Equal-length character vectors.
q Q-gram length (default 2, i.e. bigrams). Must be a single integer >= 1.
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.

Returns: numeric vector of similarities in [0, 1], length(a) long. Two strings shorter than q (so neither has any q-grams) compare equal (1).

jaccard_index("night", "nacht")
[1] 0.1428571

jaccard_matrix()

All-pairs Jaccard similarity. Same argument/return shape as jaro_winkler_matrix().

jaccard_matrix(a, b, q = 2, nthreads = NULL)

dice_coefficient() / dice_matrix()

The Sorensen-Dice coefficient: 2*|intersection| / (|A| + |B|). Weights shared q-grams more heavily than Jaccard (always >= the Jaccard score for the same pair). Same arguments as jaccard_index()/jaccard_matrix().

dice_coefficient("night", "nacht")
[1] 0.25

tversky_index() / tversky_matrix()

Generalises both: |intersection| / (|intersection| + alpha*|A only| + beta*|B only|). alpha = beta = 1 reduces to Jaccard; alpha = beta = 0.5 (the default) reduces to Dice.

tversky_index(a, b, q = 2, alpha = 0.5, beta = 0.5, nthreads = NULL)
Argument Description
a, b, q, nthreads Same as jaccard_index().
alpha, beta Tversky asymmetry weights (default 0.5 each). Non-negative scalars.
tversky_index("night", "nacht", alpha = 1, beta = 1)   # == jaccard_index()
[1] 0.1428571
tversky_index("night", "nacht", alpha = 0.5, beta = 0.5) # == dice_coefficient()
[1] 0.25

cosine_similarity() / cosine_matrix()

Builds a q-gram frequency profile for each string and returns the cosine of the angle between the two profiles — dot(A, B) / (||A|| * ||B||). Repeated q-grams keep their multiplicity, which is the whole difference from the three set metrics above.

cosine_similarity(a, b, q = 2, nthreads = NULL)
cosine_matrix(a, b, q = 2, nthreads = NULL)
Argument Description
a, b, q, nthreads Same as jaccard_index()/jaccard_matrix().

Returns: numeric vector of similarities in [0, 1], length(a) long (or a length(a) × length(b) matrix). Missing comparisons return NA. If neither string has a q-gram the similarity is 1; if only one does, it is 0.

cosine_similarity("night", "nacht")
[1] 0.25
# Multiplicity: one distinct shared bigram, but different counts
cosine_similarity("aaaa", "aaab", q = 2)
[1] 0.8944272
jaccard_index("aaaa", "aaab", q = 2)
[1] 0.5
cosine_matrix(c("JOHN SMITH", "MARY JONES"), c("JON SMYTH", "MARY JONES"))
          [,1]      [,2]
[1,] 0.5892557 0.1111111
[2,] 0.2357023 1.0000000

5.9 fuzzywuzzy-style ratios

Vectorised ports of Python’s fuzzywuzzy package, implementing the same Ratcliff/Obershelp matching-blocks algorithm fuzzywuzzy itself falls back to (the one behind Python’s difflib.SequenceMatcher). All four return 0-100 like the Python originals; see Chapter 3 for the algorithm.

fuzz_ratio(a, b, full_process = TRUE, nthreads = NULL)
fuzz_partial_ratio(a, b, full_process = TRUE, nthreads = NULL)
fuzz_token_sort_ratio(a, b, full_process = TRUE, nthreads = NULL)
fuzz_token_set_ratio(a, b, full_process = TRUE, nthreads = NULL)
Argument Description
a, b Equal-length character vectors.
full_process Logical (default TRUE, matching fuzzywuzzy’s default). Lowercases and replaces runs of non-alphanumeric characters with a single space before comparing.
nthreads Positive integer per-call thread cap, or NULL for the RcppParallel default; 1 forces serial execution.

Returns: numeric vector of scores in [0, 100], length(a) long.

  • fuzz_ratio() — overall similarity: 2*M / (len(a)+len(b)), M being the total length of the longest-common matching blocks (found recursively — not edit distance).
  • fuzz_partial_ratio() — best alignment of the shorter string against any equal-length window of the longer one.
  • fuzz_token_sort_ratio() — splits into whitespace tokens, sorts them, rejoins, then runs fuzz_ratio() — word order stops mattering.
  • fuzz_token_set_ratio() — splits into token sets and compares the shared-token core against each side’s leftovers, taking the best of three pairwise ratios — robust to one side having extra words.
fuzz_ratio("this is a test", "this is a test!")
[1] 100
fuzz_partial_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
[1] 91
fuzz_token_sort_ratio("fuzzy was a bear", "bear was a fuzzy")
[1] 100
fuzz_token_set_ratio("fuzzy was a bear", "fuzzy fuzzy bear was a bear")
[1] 100