Esercitazione: individuare le relazioni nel set di dati di Synthea usando il collegamento semantico
Questa esercitazione illustra come rilevare le relazioni nel set di dati pubblico Synthea usando il collegamento semantico.
Quando si lavora con nuovi dati o senza un modello di dati esistente, può essere utile individuare automaticamente le relazioni. Questo rilevamento delle relazioni consente di:
- comprendere il modello a livello generale,
- ottenere altre informazioni dettagliate durante l'analisi esplorativa dei dati,
- convalidare i dati aggiornati o nuovi, i dati in ingresso e
- pulire i dati.
Anche se le relazioni sono note in anticipo, una ricerca di relazioni può aiutare a comprendere meglio il modello di dati o l'identificazione dei problemi di qualità dei dati.
In questa esercitazione si inizia con un semplice esempio di base in cui si sperimentano solo tre tabelle in modo che le connessioni tra di esse siano facili da seguire. Viene quindi illustrato un esempio più complesso con un set di tabelle più grande.
In questa esercitazione apprenderai a:
- Usare i componenti del collegamento semantico della libreria Python (SemPy) che supportano l'integrazione con Power BI e consentono di automatizzare l'analisi dei dati. Questi componenti includono:
- FabricDataFrame: una struttura simile a Pandas migliorata con informazioni semantiche aggiuntive.
- Funzioni per il pull di modelli semantici da un'area di lavoro Fabric nel tuo notebook.
- Funzioni che automatizzano l'individuazione e la visualizzazione delle relazioni nei modelli semantici.
- Risolvere i problemi relativi al processo di individuazione delle relazioni per i modelli semantici con più tabelle e interdipendenze.
Prerequisiti
Ottenere una sottoscrizione di Microsoft Fabric. In alternativa, iscriversi per ottenere una versione di valutazione di Microsoft Fabric gratuita.
Accedere a Microsoft Fabric.
Usare il selettore di esperienza sul lato inferiore sinistro della home page per passare a Fabric.
- Selezionare Aree di lavoro nel riquadro di spostamento sinistro per trovare e selezionare l'area di lavoro. Questa area di lavoro diventa l'area di lavoro corrente.
Seguire la procedura nel notebook
Il notebook relationships_detection_tutorial.ipynb accompagna questa esercitazione.
Per aprire il notebook di accompagnamento per questa esercitazione, seguire le istruzioni riportate in Preparare il sistema per le esercitazioni di data science per importare il notebook nell'area di lavoro.
Se si preferisce copiare e incollare il codice da questa pagina, è possibile creare un nuovo notebook.
Assicurarsi di collegare un lakehouse al notebook prima di iniziare a eseguire il codice.
Configurare il notebook
In questa sezione viene configurato un ambiente notebook con i moduli e i dati necessari.
Installare
SemPy
da PyPI usando la funzionalità di installazione in linea%pip
all'interno del notebook:%pip install semantic-link
Eseguire le importazioni necessarie dei moduli di SemPy che serviranno in un secondo momento:
import pandas as pd from sempy.samples import download_synthea from sempy.relationships import ( find_relationships, list_relationship_violations, plot_relationship_metadata )
Importare i pandas per applicare un'opzione di configurazione utile per la formattazione dell'output:
import pandas as pd pd.set_option('display.max_colwidth', None)
Estrarre i dati di esempio. Per questa esercitazione si usa il set di dati Synthea di cartelle cliniche sintetiche (versione ridotta per semplicità):
download_synthea(which='small')
Rilevare le relazioni in un piccolo sottoinsieme di tabelle Synthea
Selezionare tre tabelle da un set più grande:
-
patients
specifica le informazioni sul paziente -
encounters
specifica i pazienti che hanno avuto incontri medici (ad esempio, un appuntamento medico, una procedura) -
providers
specifica quali operatori medici hanno frequentato i pazienti
La tabella
encounters
risolve una relazione molti-a-molti trapatients
eproviders
e può essere descritta come entità associativa:patients = pd.read_csv('synthea/csv/patients.csv') providers = pd.read_csv('synthea/csv/providers.csv') encounters = pd.read_csv('synthea/csv/encounters.csv')
-
Trovare relazioni tra le tabelle usando la funzione
find_relationships
di SemPy:suggested_relationships = find_relationships([patients, providers, encounters]) suggested_relationships
Visualizzare il DataFrame delle relazioni come grafico usando la funzione
plot_relationship_metadata
di SemPy.plot_relationship_metadata(suggested_relationships)
La funzione dispone la gerarchia delle relazioni dal lato sinistro al lato destro, che corrisponde alle tabelle "da" e "a" nell'output. In altre parole, le tabelle indipendenti "da" sul lato sinistro usano le chiavi esterne per puntare alle tabelle di dipendenza "a" sul lato destro. Ogni casella di entità mostra le colonne che partecipano al lato "da" o "a" di una relazione.
Per impostazione predefinita, le relazioni vengono generate come "m:1" (non come "1:m") o "1:1". Le relazioni "1:1" possono essere generate uno o entrambi i modi, a seconda che il rapporto dei valori mappati a tutti i valori superi
coverage_threshold
in una o in entrambe le direzioni. Più avanti in questa esercitazione viene illustrato il caso meno frequente delle relazioni "m:m".
Risolvere i problemi di rilevamento delle relazioni
L'esempio di base mostra un rilevamento delle relazioni riuscito sui dati di Synthea puliti. In pratica i dati sono raramente puliti, il che impedisce un rilevamento riuscito. Esistono diverse tecniche che possono essere utili quando i dati non sono puliti.
Questa sezione dell'esercitazione illustra il rilevamento delle relazioni quando il modello semantico contiene dati dirty.
Iniziare modificando i DataFrame originali per ottenere dati "dirty" e stampare le dimensioni dei dati dirty.
# create a dirty 'patients' dataframe by dropping some rows using head() and duplicating some rows using concat() patients_dirty = pd.concat([patients.head(1000), patients.head(50)], axis=0) # create a dirty 'providers' dataframe by dropping some rows using head() providers_dirty = providers.head(5000) # the dirty dataframes have fewer records than the clean ones print(len(patients_dirty)) print(len(providers_dirty))
Per il confronto, stampare le dimensioni delle tabelle originali:
print(len(patients)) print(len(providers))
Trovare relazioni tra le tabelle usando la funzione
find_relationships
di SemPy:find_relationships([patients_dirty, providers_dirty, encounters])
L'output del codice mostra che non sono state rilevate relazioni a causa degli errori introdotti in precedenza per creare il modello semantico "dirty".
Utilizzare la convalida
La convalida è lo strumento migliore per la risoluzione degli errori di rilevamento delle relazioni perché:
- Segnala chiaramente perché una determinata relazione non segue le regole di chiave esterna e pertanto non può essere rilevata.
- Viene eseguito rapidamente con modelli semantici di grandi dimensioni perché si concentra solo sulle relazioni dichiarate e non esegue una ricerca.
La convalida può usare qualsiasi DataFrame con colonne simili a quella generata da find_relationships
. Nel codice seguente il DataFrame suggested_relationships
fa riferimento a patients
anziché a patients_dirty
, ma è possibile eseguire l'aliasing dei DataFrame con un dizionario:
dirty_tables = {
"patients": patients_dirty,
"providers" : providers_dirty,
"encounters": encounters
}
errors = list_relationship_violations(dirty_tables, suggested_relationships)
errors
Criteri di ricerca separati
In scenari più confusi, è possibile provare ad allentare i criteri di ricerca. Questo metodo aumenta la possibilità di falsi positivi.
Impostare
include_many_to_many=True
e valutare se è utile:find_relationships(dirty_tables, include_many_to_many=True, coverage_threshold=1)
I risultati mostrano che la relazione da
encounters
apatients
è stata rilevata, ma esistono due problemi:- La relazione indica una direzione da
patients
aencounters
, che è un inverso della relazione prevista. Ciò è dovuto al fatto chepatients
è stato interamente coperto daencounters
(Coverage From
è 1,0) mentreencounters
è solo parzialmente coperto dapatients
(Coverage To
= 0,85), perché le righe dei pazienti sono mancanti. - Esiste una corrispondenza accidentale in una colonna
GENDER
di cardinalità bassa, che si verifica in base al nome e al valore in entrambe le tabelle, ma non è una relazione di interesse "m:1". La cardinalità bassa è indicata dalleUnique Count From
colonne eUnique Count To
.
- La relazione indica una direzione da
Eseguire di nuovo
find_relationships
per cercare solo le relazioni "m:1", ma con uncoverage_threshold=0.5
inferiore:find_relationships(dirty_tables, include_many_to_many=False, coverage_threshold=0.5)
Il risultato mostra la direzione corretta delle relazioni da
encounters
aproviders
. Tuttavia, la relazione daencounters
apatients
non viene rilevata perchépatients
non è univoca, quindi non può trovarsi sul lato "Uno" della relazione "m:1".Allentare sia
include_many_to_many=True
checoverage_threshold=0.5
:find_relationships(dirty_tables, include_many_to_many=True, coverage_threshold=0.5)
Ora entrambe le relazioni di interesse sono visibili, ma c'è molto più rumore:
- La corrispondenza di cardinalità bassa su
GENDER
è presente. - È apparsa una corrispondenza
ORGANIZATION
di cardinalità "m:m" più elevata, rendendo evidente che è probabile cheORGANIZATION
sia una colonna denormalizzata in entrambe le tabelle.
- La corrispondenza di cardinalità bassa su
Trovare la corrispondenza con i nomi delle colonne
Per impostazione predefinita, SemPy considera come corrispondenti solo agli attributi che mostrano la somiglianza del nome, sfruttando il fatto che le finestre di progettazione di database in genere denominano le colonne correlate allo stesso modo. Questo comportamento consente di evitare relazioni spurie, che si verificano più frequentemente con chiavi intere a cardinalità bassa. Ad esempio, se sono presenti 1,2,3,...,10
categorie di prodotti e 1,2,3,...,10
codice di stato dell'ordine, verranno confusi tra loro quando si esaminano solo i mapping dei valori senza tenere conto dei nomi di colonna. Le relazioni spurie non dovrebbero essere un problema con le chiavi simili a GUID.
SemPy esamina una somiglianza tra nomi di colonna e nomi di tabella. La corrispondenza è approssimativa e senza distinzione tra maiuscole e minuscole. Ignora le sottostringhe "decorator" rilevate più di frequente, ad esempio "id", "code", "name", "key", "pk", "fk". Di conseguenza, i casi di corrispondenza più tipici sono:
- Un attributo denominato 'column' nell'entità 'foo' corrisponde a un attributo denominato 'column' (anche 'COLUMN' o 'Column') nell'entità 'bar'.
- un attributo denominato 'column' nell'entità 'foo' corrisponde a un attributo denominato 'column_id' in 'bar'.
- Un attributo denominato 'bar' nell'entità 'foo' corrisponde a un attributo denominato 'code' in 'bar'.
Associando prima i nomi delle colonne, il rilevamento viene eseguito più velocemente.
Trovare la corrispondenza con i nomi delle colonne:
- Per comprendere quali colonne sono selezionate per un'ulteriore valutazione, usare l'opzione
verbose=2
(verbose=1
elenca solo le entità in fase di elaborazione). - Il parametro
name_similarity_threshold
determina la modalità di confronto delle colonne. La soglia di 1 indica che si è interessati solo alla corrispondenza del 100%.
find_relationships(dirty_tables, verbose=2, name_similarity_threshold=1.0);
L'esecuzione con una somiglianza del 100% non riesce a tenere conto di piccole differenze tra i nomi. Nell'esempio le tabelle hanno una forma plurale con suffisso "s", che non restituisce alcuna corrispondenza esatta. Questa operazione viene gestita correttamente con
name_similarity_threshold=0.8
per impostazione predefinita.- Per comprendere quali colonne sono selezionate per un'ulteriore valutazione, usare l'opzione
Rieseguire con
name_similarity_threshold=0.8
per impostazione predefinita:find_relationships(dirty_tables, verbose=2, name_similarity_threshold=0.8);
Si noti che l'ID per la forma
patients
plurale viene ora confrontato conpatient
singolare senza aggiungere troppi altri confronti spuri al tempo di esecuzione.Rieseguire con
name_similarity_threshold=0
per impostazione predefinita:find_relationships(dirty_tables, verbose=2, name_similarity_threshold=0);
Il passaggio da
name_similarity_threshold
a 0 è l'altro estremo e indica che si desidera confrontare tutte le colonne. Questo è raramente necessario e comporta un aumento del tempo di esecuzione e corrispondenze spurie che devono essere esaminate. Osservare il numero di confronti nell'output dettagliato.
Riepilogo dei suggerimenti per la risoluzione dei problemi
- Iniziare dalla corrispondenza esatta per le relazioni "m:1", ovvero il valore predefinito
include_many_to_many=False
ecoverage_threshold=1.0
. Questo è in genere ciò che viene richiesto. - Usare uno stato attivo stretto sui sottoinsiemi più piccoli di tabelle.
- Usare la convalida per rilevare i problemi di qualità dei dati.
- Usare
verbose=2
se si desidera comprendere quali colonne vengono considerate per la relazione. Ciò può comportare una grande quantità di output. - Tenere presente i compromessi degli argomenti di ricerca.
include_many_to_many=True
ecoverage_threshold<1.0
possono produrre relazioni spurie che potrebbero essere più difficili da analizzare e dovranno essere filtrate.
Rilevare le relazioni nel set di dati Synthea completo
L'esempio di base semplice è stato uno strumento pratico per l'apprendimento e la risoluzione dei problemi. In pratica, è possibile iniziare da un modello semantico, ad esempio il set di dati Synthea completo, che include molte più tabelle. Esplorare il set di dati Synthea completo come indicato di seguito.
Leggere tutti i file dalla directory synthea/csv:
all_tables = { "allergies": pd.read_csv('synthea/csv/allergies.csv'), "careplans": pd.read_csv('synthea/csv/careplans.csv'), "conditions": pd.read_csv('synthea/csv/conditions.csv'), "devices": pd.read_csv('synthea/csv/devices.csv'), "encounters": pd.read_csv('synthea/csv/encounters.csv'), "imaging_studies": pd.read_csv('synthea/csv/imaging_studies.csv'), "immunizations": pd.read_csv('synthea/csv/immunizations.csv'), "medications": pd.read_csv('synthea/csv/medications.csv'), "observations": pd.read_csv('synthea/csv/observations.csv'), "organizations": pd.read_csv('synthea/csv/organizations.csv'), "patients": pd.read_csv('synthea/csv/patients.csv'), "payer_transitions": pd.read_csv('synthea/csv/payer_transitions.csv'), "payers": pd.read_csv('synthea/csv/payers.csv'), "procedures": pd.read_csv('synthea/csv/procedures.csv'), "providers": pd.read_csv('synthea/csv/providers.csv'), "supplies": pd.read_csv('synthea/csv/supplies.csv'), }
Trovare relazioni tra le tabelle usando la funzione
find_relationships
di SemPy:suggested_relationships = find_relationships(all_tables) suggested_relationships
Visualizzare le relazioni:
plot_relationship_metadata(suggested_relationships)
Contare il numero di nuove relazioni "m:m" che verranno individuate con
include_many_to_many=True
. Queste relazioni si aggiungono alle relazioni "m:1" mostrate in precedenza; pertanto, è necessario filtrare in base amultiplicity
:suggested_relationships = find_relationships(all_tables, coverage_threshold=1.0, include_many_to_many=True) suggested_relationships[suggested_relationships['Multiplicity']=='m:m']
È possibile ordinare i dati delle relazioni in base a varie colonne per ottenere una comprensione più approfondita della loro natura. Ad esempio, è possibile scegliere di ordinare l'output in base a
Row Count From
eRow Count To
, che consentono di identificare le tabelle più grandi.suggested_relationships.sort_values(['Row Count From', 'Row Count To'], ascending=False)
In un modello semantico diverso, potrebbe essere importante concentrarsi sul numero di valori null
Null Count From
oCoverage To
.Questa analisi consente di comprendere se una delle relazioni potrebbe non essere valida e se è necessario rimuoverle dall'elenco dei candidati.
Contenuto correlato
Vedere altre esercitazioni per il collegamento semantico/SemPy:
- Esercitazione: Pulire i dati con dipendenze funzionali
- Esercitazione: Analizzare le dipendenze funzionali in un modello semantico di esempio
- Esercitazione: Individuare le relazioni in un modello semantico usando il collegamento semantico
- Esercitazione: Estrarre e calcolare le misure di Power BI da un Jupyter Notebook