simonedeluca / audizioni_informali

Mappatura delle audizioni informali del Senato - XVIII legislatura
MIT License
0 stars 0 forks source link

Standardizzare la nomenclatura dei soggetti/enti #2

Open simonedeluca opened 1 year ago

simonedeluca commented 1 year ago

Buon pomeriggio! Il progetto va avanti. Ho creato il dataset sulla scia delle linee guida. Sono in fase di preprocessing in vista della classificazione. Vengo al punto.

Le tabelle 'Camera.xlsx' e 'Senato.xlsx' in '_data > preprocesseddata' contengono una variabile che elenca i soggetti/enti auditi dalle commissioni rispettivamente di Camera e Senato. A causa della scarsa qualità nella condivisione delle informazioni da parte della PA, le nomenclature all'interno e tra i due dataset potrebbero non coincidere anche se riferiti alla stessa persona/organizzazione. E' necessario applicare la stessa denominazione per lo stesso soggetto/ente per finalità di classificazione e analisi.

I soggetti/enti della Camera sono stati già classificati seguendo il Registro Trasparenza del Ministero dello Sviluppo Economico. Il mio compito è classificare i soggetti/enti del Senato: [1] applicherò la categoria già individuata nel dataset sulla Camera qualora il soggetto/ente sia presente in entrambi i dataset; [2] cercherò la categoria corrispondente nel Registro Trasparenza qualora il soggetto/ente sia presente solo nel dataset del Senato.

Per il task [1] ho bisogno che la denominazione dei soggetti/enti del Senato ricalchi quella della Camera. Per il task [2] ho bisogno che la denominazione dei soggetti/enti del Senato ricalchi quella del Registro Trasparenza.

Domande Per il task [1] procedo manualmente o posso provare un approccio quantitativo? Per il task [2], ho pensato di fare lo scraping del Registro per evitare di inserire di volta in volta il nome del soggetto/ente da classificare; ma non sono riuscito a visualizzare il robots del sito e ho notato che l'url non cambia cambiando la combinazione dei filtri e scorrendo le pagine. Ha qualche suggerimento?

Un caro saluto Daje! @DeAngelisA

DeAngelisA commented 1 year ago

Ciao Simone! È difficile darti un consiglio informato su una questione cosí tecnica. Non ho mai lavorato con questi dati. Da quello che ho capito, il tuo è un problema di string matching, un challenge abbastanza comune, e normalmente molto complicato, nell'analisi dei dati. Non c'è una risposta univoca: dipende dai dati. Per me puoi provare ma alla fine ho paura che per molti casi dovrai andare un po' a mano. Ecco quello che farei io (passo all'inglese che mi è più facile):

  1. Standardizing the strings: Convert all the text to lowercase, remove extra white spaces, punctuation, and special characters to create a standardized version of each name.

Un po' di codice (non testato, scrivo al volo!)

library(tidyverse)
library(stringdist)

# Sample data
camera <- tibble(name = c("AERO CLUB D'ITALIA", "AEROCLUB D'ITALIA"))
senato <- tibble(name = c("AAPI-ANACS", "AAPI - ANACS"))

# Text standardization function
standardize_text <- function(text) {
  text %>% 
    tolower() %>%
    str_remove_all("[[:punct:]]") %>% 
    str_squish()
}

# Standardize names
camera <- camera %>% mutate(standard_name = map_chr(name, standardize_text))
senato <- senato %>% mutate(standard_name = map_chr(name, standardize_text))
  1. Puoi calcolare un qualche valore di string similarity:
# Create a similarity matrix
sim_matrix <- stringdistmatrix(camera$standard_name, senato$standard_name, method = "jw")

# Convert to long format for easier filtering
sim_matrix_long <- as.data.frame(as.table(sim_matrix))
names(sim_matrix_long) <- c("camera_idx", "senato_idx", "distance")
  1. Puoi applicare a questo punto una threshold per fare matching:
# Set a distance threshold
threshold <- 0.1

# Find matches:
matches <- sim_matrix_long %>% 
  filter(distance < threshold) %>% 
  arrange(distance)

# Add original names to matches:
matches <- matches %>% 
  left_join(camera, by = c("camera_idx" = "standard_name")) %>%
  left_join(senato, by = c("senato_idx" = "standard_name"))

# Rinomina:
names(matches) <- c("camera_standard_name", "senato_standard_name", "distance", "camera_original_name", "senato_original_name")

A questo punto, puoi visualizzare i match ambigui e risolverli a mano... Quindi diventa un processo iterativo: runni il codice sopra, verifichi a mano e correggi, togli i match verificati dal dataset, runni di nuovo sui nomi non verificati. In bocca al lupo!

simonedeluca commented 1 year ago

Salve Professore, grazie del supporto. Ho avuto modo di leggere sulla libreria "stringdist" e la procedura che propone mi porta verso la soluzione. Immaginavo si trattasse di una procedura ibrida ma l'importante è arrivarci bene. Come lei annota, conoscendo i dati si possono fare le scelte migliori, soprattutto in fase di pulizia iniziale, per ridurre la complessità della procedura. Sono riuscito a fare lo scraping del Registro (Task [2]), dunque ho anche una lista di riferimento. Direi che posso procedere, la terrò aggiornata. Have a good one!

DeAngelisA commented 1 year ago

@simonedeluca : ottimo, tienimi aggiornato! Nota che se non mi tagghi (con @) io non ricevo la mail! Un saluto!