Cette page explique comment analyser automatiquement des notions pour les racorder sous la forme d'un réseau de relations.
install.packages("readtext")
install.packages("quanteda")
install.packages("quanteda.textmodels")
install.packages("quanteda.textstats")
install.packages("quanteda.textplots")
library("readtext") # Ouverture de plusieurs documents de tous les types
library(quanteda) # textmining
quanteda_options(language_stemmer = "french")
library(quanteda.textmodels) # A installer si nécessaire.
library("quanteda.textstats")
library("quanteda.textplots")
library(igraph)
On peut télécharger un grand nombre de publications scientifiques au format pdf à partir de google scholar ou de pubmed. Le mieux est d'avoir un abonnement, plutôt que d'utiliser des cites légaux comme Scihub en s'y connectant avec VPN !
# A remplacer par l'adresse deson dossier
setwd("G:/statistiques/Textuel/Platanus/publi")
P <- readtext("*",encoding ="UTF-8")
P$text
mon_corpus <- corpus(P$text)
Chaque publication doit être coupée phrase par phrase afin qu'on analyse les mots qui se retrouvent dans la même phrase :
mon_corpus <- corpus_segment(mon_corpus, "\\.\\s[A-Z]", extract_pattern = FALSE)
library(textclean)
corpus<- replace_symbol(mon_corpus)
corpus<- replace_non_ascii(corpus,replacement="")
corpus<- strip(corpus, char.keep = "~~", digit.remove = TRUE, apostrophe.remove = F)
mes_caracteres <- table(unlist(strsplit (corpus,"")))
print(mes_caracteres)
uniq_car <- names(mes_caracteres) # pour afficher tous les types de caracteres
print(uniq_car)
library("stringr")
corpus <- str_replace_all(corpus,uniq_car[1], " ")
toks_news <- tokens(corpus,remove_punct=T,remove_numbers=F) %>%
tokens_remove(., pattern = stopwords('fr'), valuetype = 'fixed') %>% tokens_tolower(., keep_acronyms = FALSE)
library("openxlsx")
dico_perso <- read.xlsx(file.choose())
#dico_perso<- data.frame(lapply(dico_perso, function(x) {gsub(" ", "", x)}))
# Initialisation d'une liste vide
liste <- list()
# Construction de la liste avec les termes du
for(i in 1:nrow(dico_perso)){
# data.fr[i,1] = item; #str_split decompose la seconde col.
#model <- str_replace_all(dico_perso[i,2]," ","")
model <- dico_perso[i,2]
liste[dico_perso[i,1]] <- str_split(model, pattern=',')
}
liste
dic <- dictionary(liste)
Ce dictionnaire collecte tous les gènes, protéines et termes en lien avec le sujet du chancre coloré qui extermine le platane oriental (et occidental).
Une colonne pour le nom principal et une colonne Synonyme.
En bonus, on peut demander à chatgpt implémanté dans R de scanner l'ensemble des publications pour enrichir lui-même le dictionnaire (à sauvegarder à la fin avec write.xlsx() de {openxlsx}.
commande_de_base <- "J'ai un dictionnaire R (object dic) dont voici le contenu. Il contient des noms et d'éventuels synonymes (tenant compte aussi des variants liés aux pluriels ou accents). Lis le texte qui suit et produit un code R qui permettrait de mettre à jour mon dictionnaire dic en y ajoutant le vocabulaire qui te semble représentatif de ce sujet scientifique (ou en mettant éventuellement à jour les synonymes de l'ensemble des mots de dic). Attention, donne une réponse la plus simple possible, uniquement un seul bloc de code R entre des bornes ```"
library(chatgpt) # Attention, il faut aller chercher la commande exec_chatgpt_code et charger son API
tokens <- 5000
for (i in 1:length(corpus)) {
print(i)
taille <- nchar(corpus[i])
# Si mon corpus est trop grand, il va falloir le traiter par paquets
if (taille>tokens ) {
print("Traitement par paquets, trop de tokens")
diviseur <- nchar(corpus[i])%/%5000+1
for (j in 1:diviseur) {
#consigne <- paste(commande_de_base,paste(capture.output(print(dic)),collapse=" "))
consigne <-paste(commande_de_base,paste(capture.output(print(data.frame(t(unlist(dic))))),collapse=" "))
consigne <- paste(consigne," et un morceau de la publication à traiter :")
consigne <- paste(consigne, substr(corpus[i], j*tokens -(tokens -1), j*tokens ))
generated_text <- ask_chatgpt(consigne)
exec_chatgpt_code(generated_text) # Mise à jour du dictionnaire - commande à télécharger
reset_chat_session(system_role = "You are a R coder.")
}
} else {
consigne <-paste(commande_de_base,paste(capture.output(print(data.frame(t(unlist(dic))))),collapse=" "))
consigne <- paste(consigne," et un morceau de la publication à traiter :")
consigne <- paste(consigne, corpus[i])
generated_text <- ask_chatgpt(consigne)
exec_chatgpt_code(generated_text)
reset_chat_session(system_role = "You are a R coder.")
}
}
dic <- dictionary(dic)
toks_news <- tokens_lookup(toks_news, dic, exclusive=T, levels=1:2, nomatch = "_UNMATCHED")
my_dfm<- dfm(toks_news)
mywd <- dico_perso[,1] ; nperso <- length(mywd)
mymat <- fcm(toks_news, context = "window", count = "weighted", window = 12,
, ordered = TRUE, tri = FALSE)
positionr <- na.omit(match(mywd,rownames(mymat)))
positionc <- na.omit(match(mywd,colnames(mymat)))
matx <- mymat[positionr, positionc]
nrow(matx) ; matx
Le code ci-dessous permet de construire le réseau suivant et de comprendre quels groupes de gènes sont liés dans la mise en place de la maladie du chancre colorée par Ceratocystis platani chez le platane.
net <- graph_from_adjacency_matrix(matx, weighted=T)
net <- simplify(net, remove.multiple = T, remove.loops = TRUE) # élaguer les liens redondants
E(net)$arrow.size <- 0 # Exemple de sauvegarde d'un paramètre qu'on aurait plus ainsi à mettre dans comme paramètre de plot comme c'est le cas ci-dessous...
E(net)$edge.color <- "black"
# Afficher le tout en tenant compte avec betweenness du poids relatifs d'un mot pour lui donner une taille
plot(net ,vertex.size=sqrt(betweenness(net))+10,vertex.color="green",
edge.arrow.size =0,arrow.mode=0,edge.color="black")
#
clp <- cluster_optimal(net)
class(clp)
#
l <- layout_with_fr(net)
plot(clp, net, layout = l, vertex.size=sqrt(betweenness(net))+15)