Computes keyword co-occurrence, thematic components, and reference co-citation for a corpus. Records iterate in file order.
Usage
tf_litmap(
corpus,
min_link = 2,
method = "components",
min_cocitation = NULL,
min_theme_size = 2,
max_theme_size = 10,
max_df = 1
)Arguments
- corpus
A corpus object (named list), e.g. from
tf_read_corpus().- min_link
Minimum co-occurrence count for a keyword pair to be kept (default
2). A positive integer.- method
"components"(the default) or"simple_centres".- min_cocitation
Minimum count for a reference pair to be kept in
co_citation.NULL(the default) usesmin_link.- min_theme_size, max_theme_size
The smallest theme kept (default
2) and the largest a theme may grow (default10) with"simple_centres". A positive integer, and an integer of at least 2 no smaller thanmin_theme_size.- max_df
A number from 0 to 1 (default
1). With"simple_centres", a keyword in more than this share of the records is a field term, left out of the map and listed infield_terms. The three theme settings are checked with either method, although only"simple_centres"reads them.
Value
A named list with elements n_records, keywords,
keyword_cooccurrence, themes, and co_citation. With
"simple_centres", each theme also holds centrality,
density and quadrant, and the list ends with
method, parameters (the five settings used) and
field_terms.
Details
The corpus is checked before anything is counted, with the Python twin's
messages. It must hold a records list of mappings (an empty list is
an empty corpus). A keyword or reference that is an integer becomes its
decimal string, so an unquoted PubMed or Scopus id keys the same work in
both languages; one of \(2^{53}\) or more is refused, since R cannot hold
it exactly. A logical, a fraction or a nested value is refused: an unquoted
NO (nitric oxide) or on in YAML is read as a logical, so quote
it.
A reference that holds a DOI is keyed by the DOI, lower-cased and without
its resolver prefix, as tf_new_evidence_dois() compares DOIs. One work
cited as 10.1016/J.BRAT.2015.10.002 in one record and as
https://doi.org/10.1016/j.brat.2015.10.002 in another is therefore
one node, labelled 10.1016/j.brat.2015.10.002. Any other reference,
such as a Scopus or OpenAlex identifier, is compared exactly as written, and
so is every keyword.
Co-citation maps of real corpora are large. 200 OpenAlex records give about
11,000 reference pairs that share two or more citing records, so
min_cocitation can be set above min_link, and
tf_lit_diagram() can draw only the strongest edges.
method chooses how keywords are grouped into themes. With
"components", the default, a theme is a connected component of the
keyword map, and on a real corpus a few keywords shared by most records join
nearly every keyword into one. When the largest theme holds more than half
the linked keywords, a warning says so: such themes, and any landscape built
on them, do not describe the field. The result is returned unchanged.
"simple_centres" is the co-word clustering of Coulter et al. (1998)
and Cobo et al. (2011). Each link is weighted by the equivalence index
\(c^2 / (df_a df_b)\), where \(c\) counts the records holding both
keywords and \(df\) the records holding each. The strongest link between
two unassigned keywords seeds a theme, which takes its strongest unassigned
neighbour until it holds max_theme_size keywords, ties going to the
keyword first in code-point order. A keyword whose links all reach keywords
already in themes joins none. Themes smaller than min_theme_size are
dropped. Each theme gains its centrality (ten times the summed index of its
links to the keywords of other themes) and its density (100 times the
summed index of its internal links, over its size), the measures
of Callon et al. (1991) as Cobo et al. (2011) scale them. It also gains its
quadrant in the strategic diagram, split here at the median of each:
"motor" (both high), "basic" (central but not dense),
"niche" (dense but not central) or "emerging_or_declining"
(both low). On real corpora, this gives bounded themes where components give
one. Components remain the default for this release.
References
Callon, M., Courtial, J. P., & Laville, F. (1991). Co-word analysis as a tool for describing the network of interactions between basic and technological research: The case of polymer chemistry. Scientometrics, 22(1), 155-205. doi:10.1007/BF02019280
Coulter, N., Monarch, I., & Konda, S. (1998). Software engineering as seen through its research literature: A study in co-word analysis. Journal of the American Society for Information Science, 49(13), 1206-1223.
Cobo, M. J., López-Herrera, A. G., Herrera-Viedma, E., & Herrera, F. (2011). An approach for detecting, quantifying, and visualizing the evolution of a research field: A practical application to the Fuzzy Sets Theory field. Journal of Informetrics, 5(1), 146-166. doi:10.1016/j.joi.2010.10.002
Examples
corpus <- list(
schema_version = "1.0", id = "demo-corpus",
records = list(
list(id = "w1", keywords = list("arousal", "threat")),
list(id = "w2", keywords = list("arousal", "threat")),
list(id = "w3", keywords = list("avoidance", "exposure")),
list(id = "w4", keywords = list("avoidance", "exposure"))
)
)
tf_litmap(corpus)
#> $n_records
#> [1] 4
#>
#> $keywords
#> $keywords[[1]]
#> [1] "arousal"
#>
#> $keywords[[2]]
#> [1] "avoidance"
#>
#> $keywords[[3]]
#> [1] "exposure"
#>
#> $keywords[[4]]
#> [1] "threat"
#>
#>
#> $keyword_cooccurrence
#> $keyword_cooccurrence[[1]]
#> $keyword_cooccurrence[[1]]$a
#> [1] "arousal"
#>
#> $keyword_cooccurrence[[1]]$b
#> [1] "threat"
#>
#> $keyword_cooccurrence[[1]]$count
#> [1] 2
#>
#>
#> $keyword_cooccurrence[[2]]
#> $keyword_cooccurrence[[2]]$a
#> [1] "avoidance"
#>
#> $keyword_cooccurrence[[2]]$b
#> [1] "exposure"
#>
#> $keyword_cooccurrence[[2]]$count
#> [1] 2
#>
#>
#>
#> $themes
#> $themes[[1]]
#> $themes[[1]]$id
#> [1] "theme_1"
#>
#> $themes[[1]]$keywords
#> $themes[[1]]$keywords[[1]]
#> [1] "arousal"
#>
#> $themes[[1]]$keywords[[2]]
#> [1] "threat"
#>
#>
#> $themes[[1]]$size
#> [1] 2
#>
#>
#> $themes[[2]]
#> $themes[[2]]$id
#> [1] "theme_2"
#>
#> $themes[[2]]$keywords
#> $themes[[2]]$keywords[[1]]
#> [1] "avoidance"
#>
#> $themes[[2]]$keywords[[2]]
#> [1] "exposure"
#>
#>
#> $themes[[2]]$size
#> [1] 2
#>
#>
#>
#> $co_citation
#> list()
#>
# Simple centres on the frozen OpenAlex corpus, where components give one
# theme.
openalex <- tf_read_corpus(tf_example_path("openalex-panic-2026.corpus.yaml"))
lm <- tf_litmap(openalex, method = "simple_centres")
table(vapply(lm$themes, function(th) th$quadrant, character(1)))
#>
#> basic emerging_or_declining motor
#> 5 3 4
#> niche
#> 5