Condividi tramite


Esercitazione: Individuare le relazioni nel set di dati Synthea usando il collegamento semantico

Questa esercitazione illustra come rilevare le relazioni nel set di dati Synthea pubblico 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 della libreria Python (SemPy) del collegamento semantico che supportano l'integrazione con Power BI e consentono di automatizzare l'analisi dei dati. Questi componenti includono:
    • FabricDataFrame: struttura simile a pandas migliorata con informazioni semantiche aggiuntive.
    • Funzioni per il pull di modelli semantici da un'area di lavoro fabric nel 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

  • 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 a accompagnamento per questa esercitazione, seguire le istruzioni riportate in Preparare il sistema per le esercitazioni sull'analisi scientifica dei dati 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.

  1. Eseguire l'installazione SemPy da PyPI usando la %pip funzionalità di installazione in linea all'interno del notebook:

    %pip install semantic-link
    
  2. Eseguire le importazioni necessarie dei moduli SemPy necessari 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
    )
    
  3. Importare pandas per applicare un'opzione di configurazione utile per la formattazione dell'output:

    import pandas as pd
    pd.set_option('display.max_colwidth', None)
    
  4. Eseguire il pull dei dati di esempio. Per questa esercitazione si usa il set di dati Synthea di record medici sintetici (versione ridotta per semplicità):

    download_synthea(which='small')
    

Rilevare le relazioni in un piccolo subset di tabelle Synthea

  1. 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 encounters tabella risolve una relazione molti-a-molti tra patients e providers 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')
    
  2. Trovare relazioni tra le tabelle usando la funzione di find_relationships SemPy:

    suggested_relationships = find_relationships([patients, providers, encounters])
    suggested_relationships
    
  3. Visualizzare le relazioni dataframe come grafico usando la funzione di plot_relationship_metadata SemPy.

    plot_relationship_metadata(suggested_relationships)
    

    Screenshot che mostra le relazioni tra tabelle nel set di dati.

    La funzione dispone la gerarchia delle relazioni dal lato sinistro al lato destro, che corrisponde alle tabelle "from" e "to" 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 "from" o "to" 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 una o 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, che impediscono il rilevamento riuscito. Esistono diverse tecniche che possono essere utili quando i dati non sono puliti.

Questa sezione di questa esercitazione illustra il rilevamento delle relazioni quando il modello semantico contiene dati dirty.

  1. 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))
    
    
  2. Per il confronto, le dimensioni di stampa delle tabelle originali:

    print(len(patients))
    print(len(providers))
    
  3. Trovare relazioni tra le tabelle usando la funzione di find_relationships 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".

Usare 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 suggested_relationships dataframe fa riferimento a patients anziché patients_dirtya , 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ù oscuro, è possibile provare ad allentare i criteri di ricerca. Questo metodo aumenta la possibilità di falsi positivi.

  1. 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 a patients è stata rilevata, ma esistono due problemi:

    • La relazione indica una direzione da patients a encounters, che è un inverso della relazione prevista. Ciò è dovuto al fatto che tutto patients è stato coperto da encounters (Coverage From è 1,0) mentre encounters sono solo parzialmente coperti da patients (Coverage To = 0,85), perché le righe dei pazienti sono mancanti.
    • Esiste una corrispondenza accidentale in una colonna di cardinalità GENDER 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 dalle Unique Count From colonne e Unique Count To .
  2. find_relationships Eseguire di nuovo per cercare solo le relazioni "m:1", ma con un valore inferiorecoverage_threshold=0.5:

    find_relationships(dirty_tables, include_many_to_many=False, coverage_threshold=0.5)
    

    Il risultato mostra la direzione corretta delle relazioni da encounters a providers. Tuttavia, la relazione da encounters a patients non viene rilevata perché patients non è univoca, quindi non può trovarsi sul lato "Uno" della relazione "m:1".

  3. Allentare sia che include_many_to_many=True coverage_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.
    • È stata visualizzata una corrispondenza ORGANIZATION di cardinalità "m:m" più elevata, rendendo evidente che è probabile che ORGANIZATION una colonna de normalizzata in entrambe le tabelle.

Trova la corrispondenza con i nomi delle colonne

Per impostazione predefinita, SemPy considera corrisponde 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 integer a cardinalità bassa. Ad esempio, se sono 1,2,3,...,10 presenti 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.

  1. 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 name_similarity_threshold parametro 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 l'oggetto predefinito name_similarity_threshold=0.8.

  2. Rieseguire con l'impostazione predefinita name_similarity_threshold=0.8:

    find_relationships(dirty_tables, verbose=2, name_similarity_threshold=0.8);
    

    Si noti che l'ID per la forma patients plurale viene ora confrontato con singolare patient senza aggiungere troppi altri confronti spuri al tempo di esecuzione.

  3. Rieseguire con l'impostazione predefinita name_similarity_threshold=0:

    find_relationships(dirty_tables, verbose=2, name_similarity_threshold=0);
    

    Il passaggio 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

  1. Iniziare dalla corrispondenza esatta per le relazioni "m:1", ovvero il valore predefinito include_many_to_many=False e coverage_threshold=1.0. Questo è in genere ciò che vuoi.
  2. Usare uno stato attivo stretto sui subset più piccoli di tabelle.
  3. Usare la convalida per rilevare i problemi di qualità dei dati.
  4. Usare verbose=2 se si desidera comprendere quali colonne vengono considerate per la relazione. Ciò può comportare una grande quantità di output.
  5. Tenere presente i compromessi degli argomenti di ricerca. include_many_to_many=True e coverage_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.

  1. 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'),
    }
    
  2. Trovare relazioni tra le tabelle usando la funzione di find_relationships SemPy:

    suggested_relationships = find_relationships(all_tables)
    suggested_relationships
    
  3. Visualizzare le relazioni:

    plot_relationship_metadata(suggested_relationships)
    

    Screenshot delle relazioni tra tabelle.

  4. 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 multiplicitya :

    suggested_relationships = find_relationships(all_tables, coverage_threshold=1.0, include_many_to_many=True) 
    suggested_relationships[suggested_relationships['Multiplicity']=='m:m']
    
  5. È 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 Row Count From base a e Row 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 o Coverage To.

    Questa analisi consente di comprendere se una delle relazioni potrebbe non essere valida e se è necessario rimuoverle dall'elenco dei candidati.

Vedere altre esercitazioni per il collegamento semantico/SemPy: