Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export(count_vec)
export(entity_list_2_graph2)
export(extract_entities_l)
export(extract_entities_v)
export(extract_entity)
export(extract_graph)
export(extract_entity_rb)
export(extract_graph_df)
export(extract_graph_pos)
export(extract_graph_rb)
export(extract_relation)
export(extract_triplets)
export(filter_by_query)
Expand All @@ -25,7 +25,9 @@ export(get_cooc_entities)
export(get_entities)
export(get_graph_from_txt)
export(get_neighbors)
export(get_neighbors_df)
export(get_node_id)
export(graph_from_cooccurrence)
export(graph_subs)
export(group_entities)
export(group_ppn)
Expand Down
9 changes: 6 additions & 3 deletions R/cooccur_word.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ cooccur_words <- function(
} else if (token_by %in% c("par", "paragraph")) {
# tokens <- tokenizers::tokenize_paragraphs(text)
# tokens <- lapply(text, tokenizers::tokenize_paragraphs)
tokens <- plyr::llply(
# tokens <- plyr::llply(
tokens <- purrr::map(
text,
\(X) {
# tokens <- lapply(text, \(X) {
Expand All @@ -72,7 +73,8 @@ cooccur_words <- function(
# word_tokens_list <- unlist(tokens) |>
# word_tokens_list <- lapply(tokens, \(X) {
message("tokenizing words...")
word_tokens_list <- plyr::llply(
# word_tokens_list <- plyr::llply(
word_tokens_list <- purrr::map(
tokens,
\(X) {
# tokenizers::tokenize_words(X, lowercase = lower)
Expand Down Expand Up @@ -175,7 +177,8 @@ cooccur_words <- function(

total <- length(comb_list)
# lst <- lapply(seq_along(comb_list), \(X) {
lst <- plyr::llply(
# lst <- plyr::llply(
lst <- purrr::map(
seq_along(comb_list),
function(X) {
percent <- ((X / total) * 100)
Expand Down
172 changes: 55 additions & 117 deletions R/entity_link.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ rgx_abbrev <- "([:upper:]\\.){2,}"
rgx_word <- "(\\b[A-ZÀ-ß][A-ZÀ-ßa-zà-ÿ0-9\\.\\-]+\\b)"


#' list of proper names connectors
#'
#' @description
#' list of connectors between proper names in different languages
connectors_list <- list(
pt = c("da", "das", "de", "do", "dos"),
es = "del",
en = c("of", "of the"),
misc = c("of", "the", "of the", "von", "van", "del", "de"),
it = "di",
ho = "van"
)

#' A lowercase connectors between two proper names
#'
#' In some languages there is a lowercase connector between two or more proper names.
Expand All @@ -19,87 +32,52 @@ rgx_word <- "(\\b[A-ZÀ-ß][A-ZÀ-ßa-zà-ÿ0-9\\.\\-]+\\b)"
#' connectors("en")
#' connectors("misc")
connectors <- function(lang = "pt") {
# conn_pt <- c("da", "das", "de", "do", "dos")
# conn_es <- "del"
# conn_en <- c("of", "of the")
# conn_misc <- c("of", "the", "of the", "von", "van", "del")

if (
lang %in% c("pt", "por", "port", "portugues", "português", "portuguese")
) {
conn <- c("da", "das", "de", "do", "dos")
conn <- connectors_list["pt"]
# } else if (lang %in% s2v("es spa spanish espanol español")) {
} else if (lang %in% c("es", "spa", "spanish", "espanol", "español")) {
conn <- "del"
} else if (
lang %in% c("es", "spa", "span", "spanish", "espanol", "español")
) {
conn <- connectors_list["es"]
# } else if (lang %in% s2v("en eng english inglês")) {
} else if (lang %in% c("en", "eng", "english", "inglês")) {
conn <- c("of", "of the")
conn <- connectors_list["en"]
} else if (lang %in% c("it", "ita", "italian", "italiano")) {
conn <- connectors_list["it"]
} else if (lang %in% c("ho", "hol", "niederland")) {
conn <- connectors_list["ho"]
} else if (lang == "misc") {
# conn <- "of the of_the von van del"
conn <- c("of", "the", "of the", "von", "van", "del")
conn <- connectors_list["misc"]
} else if (lang == "all") {
conn <- unlist(connectors_list) |> sort() |> unique()
} else {
paste("Lang not found:", lang) |> stop()
}

# conn |> s2v()
conn
return(conn)
}

#' A rule based entity extractor
#' extracts the entity from a text using regex. This regex captures all uppercase words, words that begin with upper case. If there is sequence of this patterns together, this function also captures.
#' In the case of proper names with common lower case connectors like "Wwwww of Wwwww" this function also captures the connector and the subsequent uppercase words.
#' @param text an input text
#' @param connect a vector of lowercase connectors. Use use your own, or use the function "connector" to obtain some patterns.
#' @param sw a vector of stopwords
#' @param underscore keep underscore to make compounded words a unique word?
#' @export
#' @examples
#' "John Does lives in New York in United States of America." |> extract_entity()
#' "João Ninguém mora em São José do Rio Preto. Ele esteve antes em Sergipe" |> extract_entity(connect = connectors("pt"))
# text |> extract_entity()
extract_entity <- function(
text,
connect = connectors("misc"),
sw = "the",
underscore = TRUE) {
# connectors <- connectors |> s2v()
connector <- paste(connect, collapse = "|") |> gsub("(.*)", "(\\1)", x = _)

# rgx_ppn <- paste0("(", rgx_word, "+ ?)+", "", connector, "? (", rgx_word, " ?)*")
rgx_ppn <- paste0(
"(",
rgx_word,
"+ ?)+",
"(",
connector,
"? (",
rgx_word,
" ?)+)*"
)

text_vec <- text |>
stringr::str_extract_all(rgx_ppn) |>
unlist() |>
stringr::str_trim()
# trimws()

# deleting stopword elements
text_vec <- text_vec[!text_vec %in% stringr::str_to_title(sw)]

if (underscore) {
gsub(x = text_vec, " ", "_")
} else {
text_vec
}
}

#TODO gen_stopwords neste exemplo
# TODO gen_stopwords neste exemplo

#' Substitute proper names/entities spaces with underscore in the text.
#'
#' given a text and a vector of entities, it substitutes the spaces with underscores, so the entities are identified.
#'
#' @param text an input text
#' @param entities an input vector, as exported by `extract_entity()`
#' @param entities an input vector, as exported by `extract_entity_rb()`
#' @export
#' @examples
#' texto_teste <- "José da Silva e Fulano de Tal foram, bla Maria Silva. E depois disso, bla Joaquim José da Silva Xavier no STF"
#' ppn <- texto_teste |> extract_entity(connectors("pt"), sw = gen_stopwords("pt"))
#' ppn <- texto_teste |> extract_entity_rb(connectors("pt"), sw = gen_stopwords("pt"))
#' texto_teste |> subs_ppn(ppn)
#' texto_teste |> subs_ppn(ppn, method = "loop")
#' text <- texto_teste |> subs_ppn(ppn)
Expand All @@ -109,7 +87,7 @@ extract_entity <- function(
# unlist() |>
# count_vec()
subs_ppn <- function(text, entities, method = "normal") {
# entities <- texto_teste |> extract_entity(connectors("pt"), sw = gen_stopwords("pt"))
# entities <- texto_teste |> extract_entity_rb(connectors("pt"), sw = gen_stopwords("pt"))
entities <- entities |> unlist()

if (method == "loop") {
Expand Down Expand Up @@ -151,10 +129,11 @@ subs_ppn <- function(text, entities, method = "normal") {
#' "John Does lives in New York in United States of America." |> extract_relation()
#' "João Ninguém mora em São José do Rio Preto. Ele foi para o Rio de Janeiro." |> extract_relation(connector = connectors("pt"))
extract_relation <- function(
text,
using = "sentences",
connect = connectors("misc"),
sw = gen_stopwords("en")) {
text,
using = "sentences",
connect = connectors("misc"),
sw = gen_stopwords("en")
) {
if (using == "sentences" || using == "sent") {
message("Tokenizing by sentences")
list_w <- text |>
Expand All @@ -170,7 +149,7 @@ extract_relation <- function(
list_w <- lapply(
X = list_w,
\(txt) {
extract_entity(txt, connect = connect, sw = sw)
extract_entity_rb(txt, connect = connect, sw = sw)
}
)

Expand All @@ -182,49 +161,6 @@ extract_relation <- function(
list_w[list_length > 1] #|> lapply(combn, 2, simplify = TRUE)
}

#' Extract a non directional graph based on co-occurrence in the token.
#' It extracts only if two entities are mentioned in the same token (sentence or paragraph)
#' @param text an input text
#' @param using sentence or paragraph to tokenize
#' @param connect lowercase connectors, like the "von" in "John von Neumann".
#' @param sw stopwords vector.
#' @param loop if TRUE, it will not remove loops, a node pointing to itself.
#' @export
#' @examples
#' text <- "John Does lives in New York in United States of America. He is a passionate jazz musician, often playing in local clubs."
#' extract_graph(text)
extract_graph <- function(
text,
using = "sentences",
connect = connectors("misc"),
sw = c("of", "the"),
loop = FALSE) {
list_ent <- text |> extract_relation(using, connect, sw)
graph <- tibble::tibble(n1 = as.character(""), n2 = as.character(""))
# list_length <- list_ent |> length()

graph <- lapply(list_ent, \(e) {
items <- e |> combn(2, simplify = FALSE)
items_length <- length(items)
lapply(1:items_length, \(x) {
line <- unlist(c(items[x][1], items[x][2]))
graph <- rbind(graph, line)
graph
}) |>
dplyr::bind_rows() |>
dplyr::filter(n1 != "")
}) |>
dplyr::bind_rows()

if (!loop) {
graph <- graph |>
dplyr::mutate(loop = (n1 == n2)) |>
dplyr::filter(loop == FALSE) |>
dplyr::select(-loop)
}
return(graph)
}


#' Extract a non directional graph based on co-occurrence in the token and returns a tibble
#' It extracts only if two entities are mentioned in the same token (sentence or paragraph)
Expand All @@ -244,13 +180,14 @@ extract_graph <- function(
#' DF <- data.frame(text = c("John Does lives in New York in United States of America. He is a passionate jazz musician, often playing in local clubs.", r"(John Michael "Ozzy" Osbourne (3 December 1948 – 22 July 2025) was an English singer, songwriter, and media personality. He co-founded the pioneering heavy metal band Black Sabbath in 1968, and rose to prominence in the 1970s as their lead vocalist. During this time, he adopted the title "Prince of Darkness".[3][4] He performed on the band's first eight albums, most notably including Black Sabbath, Paranoid (both 1970) and Master of Reality (1971), before he was fired in 1979 due to his problems with alcohol and other drugs.)")) |> dplyr::mutate(id = paste0("id_", dplyr::row_number()))
#' extract_graph_df(DF, "id", "text")
extract_graph_df <- function(
df,
column_id,
column_text,
using = "sentences",
connect = connectors("misc"),
sw = c("of", "the"),
loop = FALSE) {
df,
column_id,
column_text,
using = "sentences",
connect = connectors("misc"),
sw = c("of", "the"),
loop = FALSE
) {
df_out <- list()

for (i in 1:nrow(DF)) {
Expand All @@ -268,10 +205,11 @@ extract_graph_df <- function(
#' @return a graph
#' keywords internal
extract_graph_rgx <- function(
text,
pattern,
sw = gen_stopwords("en"),
count_graphs = FALSE) {
text,
pattern,
sw = gen_stopwords("en"),
count_graphs = FALSE
) {
text
# TODO
}
1 change: 1 addition & 0 deletions R/escape_regex.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#' escape_regex("Dr. John", word_delim = TRUE)
#' # pattern is "\\bDr\\.John\\b"
#'
#' @noRd
escape_regex <- function(string, word_delim = FALSE) {
# string <- gsub("([.[\\(*+?{|^$])", "\\\\\\1", string)
string <- string |>
Expand Down
52 changes: 52 additions & 0 deletions R/extract_entity_rb.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#' A rule based entity extractor
#'
#' @description
#' extracts the entity from a text using regex. This regex captures all uppercase words, words that begin with upper case. If there is sequence of this patterns together, this function also captures.
#' In the case of proper names with common lower case connectors like "Wwwww of Wwwww" this function also captures the connector and the subsequent uppercase words.
#'
#' @param text an input text
#' @param connect a vector of lowercase connectors. Use use your own, or use the function "connector" to obtain some patterns.
#' @param sw a vector of stopwords
#' @param underscore keep underscore to make compounded words a unique word?
#'
#' @export
#'
#' @examples
#' "John Does lives in New York in United States of America." |> extract_entity()
#' "João Ninguém mora em São José do Rio Preto. Ele esteve antes em Sergipe" |> extract_entity(connect = connectors("pt"))
#' text |> extract_entity()
extract_entity_rb <- function(
text,
connect = connectors("misc"),
sw = "the",
underscore = TRUE) {
# connectors <- connectors |> s2v()
connector <- paste(connect, collapse = "|") |> gsub("(.*)", "(\\1)", x = _)

# rgx_ppn <- paste0("(", rgx_word, "+ ?)+", "", connector, "? (", rgx_word, " ?)*")
rgx_ppn <- paste0(
"(",
rgx_word,
"+ ?)+",
"(",
connector,
"? (",
rgx_word,
" ?)+)*"
)

text_vec <- text |>
stringr::str_extract_all(rgx_ppn) |>
unlist() |>
stringr::str_trim()
# trimws()

# deleting stopword elements
text_vec <- text_vec[!text_vec %in% stringr::str_to_title(sw)]

if (underscore) {
gsub(x = text_vec, " ", "_")
} else {
text_vec
}
}
Loading