Turn phrases, spaCy-style pattern lists or a data.frame of patterns into a
spacyr_entity_patterns object: a checked set of rules for spaCy's
entity_ruler, which finds named entities by matching phrases or sequences
of tokens. Creating the object needs neither Python nor spaCy; pass it to
spacy_initialize() as entity_patterns to add the rules to the pipeline.
Usage
as_entity_patterns(x, ...)
# S3 method for class 'character'
as_entity_patterns(x, label = NULL, id = NULL, case_insensitive = FALSE, ...)
# S3 method for class 'list'
as_entity_patterns(x, case_insensitive = FALSE, ...)
# S3 method for class 'data.frame'
as_entity_patterns(x, case_insensitive = FALSE, concatenator = NULL, ...)
# S3 method for class 'dictionary2'
as_entity_patterns(
x,
case_insensitive = TRUE,
valuetype = c("glob", "fixed", "regex"),
...
)Arguments
- x
the patterns to convert:
a character vector of phrases, each matched exactly as a sequence of spaCy's tokens. Labels come from the names of
x, as inc(ORG = "Acme Widgets"), or fromlabel.a list of patterns in spaCy's own structure, each a list with the elements
label,patternand optionallyid.patternis either a single phrase or a list of token patterns, one per token, each a named list of token attributes such aslist(LOWER = "dr"). See spaCy's rule-based matching for the attributes and operators available. A single pattern may also be given on its own, rather than in a list of patterns.a data.frame with the columns
labelandpattern, and optionallyidandcase_insensitive.patternis a character column of phrases, or a list column holding phrases or token patterns.the entities found by
spacy_extract_entity(), a data.frame with the columnstextandent_type, which become phrases and their labels. This turns the entities found in one set of texts into rules for others.the entities found by
entity_extract(), with the columnsentityandentity_type, given with theconcatenatorthat joined their tokens.a quanteda dictionary, made by
quanteda::dictionary(). Its top-level keys are the labels, with the values of any nested keys under them. A value without wildcards becomes a phrase. A value with wildcards (*for any characters,?for one) becomes a token pattern with one token for each part separated by spaces, as quanteda matches dictionary values to tokens, so that"dr * who"matches three tokens.NULL, asspacy_extract_entity()returns when it finds no entities, which gives an empty set of patterns.a
spacyr_entity_patternsobject, which is checked again, since it may have been edited as a data.frame.
- ...
not used.
- label
character; the entity label of each phrase, such as
"PERSON"or"ORG", either one for all phrases or one per phrase. IfNULL(the default), the names ofxare used.- id
character; an optional ID for each phrase, either one for all phrases or one per phrase. spaCy gives the ID of the pattern that matched as each entity's
ent_id_.- case_insensitive
logical; if
TRUE, phrases match regardless of case. The default,FALSE, matches them exactly, as spaCy does, except for a dictionary, where it isTRUE, as in quanteda, and also applies to the parts of values with wildcards. It does not apply to token patterns, which set case through the attribute they match, such asORTH(exact) orLOWER(any case). For a list, it applies to the patterns that do not setcase_insensitivethemselves; for a data.frame, it applies when there is nocase_insensitivecolumn.- concatenator
for the output of
entity_extract(), the character(s) that joined the tokens of each entity, which are replaced by spaces. It must be given, since a token that itself contains the concatenator, such as an underscore, is changed too; the output ofspacy_extract_entity()keeps the text of each entity as it was, and is the better input.- valuetype
for a dictionary, how its values are matched:
"glob"(the default) for wildcards,"fixed"for exact phrases, or"regex"for regular expressions, as inquanteda::tokens_lookup(). With"regex", each part of a value separated by spaces is a regular expression for one of spaCy's tokens, in the dialect of Python'sremodule, not of R: for instance,"^\\p{L}+$"works in quanteda but stopsspacy_initialize()with the error "bad escape \p". Sincequanteda::dictionary()lowercases values by default, which changes escapes such as"\\D"to"\\d", make a dictionary of regular expressions withtolower = FALSE.
Value
A spacyr_entity_patterns object: a data.frame with one row per
pattern and the columns
labelthe entity label;patterna list column, holding for each pattern a single phrase or a list of token patterns;idthe pattern's ID, orNA;case_insensitivefor phrases, whether they match regardless of case;NAfor token patterns.
Duplicated patterns are removed.
Details
Token patterns are checked for their structure only: that each is a list with one named list per token. spaCy checks the attribute names, operators and values when the patterns are added to a pipeline, and reports any errors then.
Two conversions make patterns from R reach spaCy in the form it expects.
The values of spaCy's set operators (IN, NOT_IN, IS_SUBSET,
IS_SUPERSET and INTERSECTS) are always stored as lists, so that
list(LOWER = list(IN = "dr")) stays a list of one value, rather than
becoming a single string. Whole numbers stored as doubles, such as 3
in list(LENGTH = 3), become integers, since spaCy does not accept
decimal numbers in token patterns.
Phrases, including dictionary values without wildcards, are split into
tokens by the pipeline's own tokenizer, and some of its rules depend on
case: spaCy's English models keep "Inc." as one token, but split
"inc." into "inc" and ".". So write phrases in their usual case, even with
case_insensitive = TRUE, and make dictionaries with
quanteda::dictionary(tolower = FALSE), since by default it lowercases
their values.
Patterns match spaCy's tokens, not characters. For instance, spaCy's
English models make "Prof." a single token, so a pattern for academic
titles needs to list both "prof" and "prof.", to match titles written
with and without a full stop.
See also
entity_patterns_read() and entity_patterns_write() to read
and write patterns as files, and spacy_initialize() to use them
Examples
# phrases, labelled by their names or by `label`
as_entity_patterns(c(ORG = "Acme Widgets", GPE = "San Francisco"))
#> Entity patterns: 2 patterns (ORG: 1, GPE: 1)
#> ORG "Acme Widgets"
#> GPE "San Francisco"
as_entity_patterns(c("Acme Widgets", "Globex"), label = "ORG")
#> Entity patterns: 2 patterns (ORG: 2)
#> ORG "Acme Widgets"
#> ORG "Globex"
# a token pattern for people with academic titles: a title, followed by
# the first token of a person the model recognises (ENT_IOB "B") and the
# rest of that person (ENT_IOB "I"), so that it extends one entity without
# running into a person who follows it
titles <- c("dr", "dr.", "prof", "prof.")
as_entity_patterns(list(
label = "PERSON",
pattern = list(list(LOWER = list(IN = titles)),
list(ENT_TYPE = "PERSON", ENT_IOB = "B"),
list(ENT_TYPE = "PERSON", ENT_IOB = "I", OP = "*"))
))
#> Entity patterns: 1 pattern (PERSON: 1)
#> PERSON [LOWER in (dr, dr., prof, prof.)] [ENT_TYPE = PERSON, ENT_IOB = B] [ENT_TYPE = PERSON, ENT_IOB = I]*
# a data.frame of patterns
as_entity_patterns(data.frame(label = c("ORG", "ORG"),
pattern = c("Acme Widgets", "Globex")))
#> Entity patterns: 2 patterns (ORG: 2)
#> ORG "Acme Widgets"
#> ORG "Globex"
# a quanteda dictionary, with labels from its keys
if (requireNamespace("quanteda", quietly = TRUE)) {
dict <- quanteda::dictionary(list(ORG = c("acme widgets", "globex*"),
PERSON = "dr * who"))
as_entity_patterns(dict)
}
#> Entity patterns: 3 patterns (ORG: 2, PERSON: 1)
#> ORG "acme widgets" (any case)
#> ORG [LOWER ~ /^globex.*$/]
#> PERSON [LOWER = dr] [LOWER ~ /^.*$/] [LOWER = who]
# entities found by spaCy, to use as rules for other texts
if (FALSE) { # \dontrun{
spacy_initialize()
found <- spacy_extract_entity("Acme Widgets hired Jane Smith.")
as_entity_patterns(found)
spacy_finalize()
} # }
# combine sets of patterns
c(as_entity_patterns(c(ORG = "Globex")),
as_entity_patterns(c(PERSON = "Jane Smith")))
#> Entity patterns: 2 patterns (ORG: 1, PERSON: 1)
#> ORG "Globex"
#> PERSON "Jane Smith"