Delen via


Zelfstudie: Relaties ontdekken in de Synthea-gegevensset met behulp van een semantische koppeling

In deze zelfstudie ziet u hoe u relaties in de openbare Synthea-gegevensset detecteert met behulp van een semantische koppeling.

Wanneer u met nieuwe gegevens werkt of zonder een bestaand gegevensmodel werkt, kan het handig zijn om automatisch relaties te detecteren. Deze relatiedetectie kan u helpen bij het volgende:

  • het model op hoog niveau begrijpen,
  • krijg meer inzichten tijdens verkennende gegevensanalyse,
  • bijgewerkte gegevens of nieuwe, binnenkomende gegevens valideren en
  • gegevens opschonen.

Zelfs als relaties van tevoren bekend zijn, kan een zoekopdracht naar relaties helpen bij een beter begrip van het gegevensmodel of het identificeren van problemen met de kwaliteit van gegevens.

In deze zelfstudie begint u met een eenvoudig basislijnvoorbeeld waarin u met slechts drie tabellen experimenteert, zodat verbindingen tussen deze tabellen eenvoudig te volgen zijn. Vervolgens geeft u een complexer voorbeeld weer met een grotere tabelset.

In deze zelfstudie leert u het volgende:

  • Gebruik onderdelen van de Python-bibliotheek (SemPy) van semantische koppelingen die ondersteuning bieden voor integratie met Power BI en om gegevensanalyse te automatiseren. Deze onderdelen zijn onder andere:
    • FabricDataFrame- een pandas-achtige structuur die is uitgebreid met aanvullende semantische informatie.
    • Functies voor het ophalen van semantische modellen uit een Fabric-werkruimte in uw notebook.
    • Functies waarmee de detectie en visualisatie van relaties in uw semantische modellen wordt geautomatiseerd.
  • Los het proces van relatiedetectie voor semantische modellen met meerdere tabellen en afhankelijkheden op.

Vereisten

  • Selecteer Werkruimten in het linkernavigatiedeelvenster om uw werkruimte te zoeken en te selecteren. Deze werkruimte wordt uw huidige werkruimte.

Volgen in het notitieblok

De notebook relationships_detection_tutorial.ipynb begeleidt deze zelfstudie.

Als u het bijbehorende notitieblok voor deze zelfstudie wilt openen, volgt u de instructies in Uw systeem voorbereiden voor zelfstudies voor gegevenswetenschap om het notebook te importeren in uw werkruimte.

Als u liever de code van deze pagina kopieert en plakt, kunt u een nieuw notitieblok maken.

Zorg ervoor dat u een lakehouse aan het notebook koppelt voordat u begint met het uitvoeren van code.

Het notebook instellen

In deze sectie stelt u een notebookomgeving in met de benodigde modules en gegevens.

  1. Installeren SemPy vanuit PyPI met behulp van de %pip inline-installatiemogelijkheid in het notebook:

    %pip install semantic-link
    
  2. Voer de benodigde importbewerkingen uit van SemPy-modules die u later nodig hebt:

    import pandas as pd
    
    from sempy.samples import download_synthea
    from sempy.relationships import (
        find_relationships,
        list_relationship_violations,
        plot_relationship_metadata
    )
    
  3. Importeer pandas voor het afdwingen van een configuratieoptie die helpt bij het opmaken van uitvoer:

    import pandas as pd
    pd.set_option('display.max_colwidth', None)
    
  4. Haal de voorbeeldgegevens op. Voor deze zelfstudie gebruikt u de Synthea-gegevensset van synthetische medische records (kleine versie voor eenvoud):

    download_synthea(which='small')
    

Relaties detecteren op een kleine subset van Synthea-tabellen

  1. Selecteer drie tabellen uit een grotere set:

    • patients geeft patiëntinformatie op
    • encounters geeft de patiënten aan die medische ontmoeting hadden (bijvoorbeeld een medische afspraak, procedure)
    • providers geeft aan welke medische dienstverleners aan de patiënten zijn deelgenomen

    De encounters tabel lost een veel-op-veel-relatie tussen patients en providers kan worden beschreven als een associatieve entiteit:

    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. Zoek relaties tussen de tabellen met behulp van de functie van SemPy find_relationships :

    suggested_relationships = find_relationships([patients, providers, encounters])
    suggested_relationships
    
  3. Visualiseer de relaties dataframe als een grafiek met behulp van de functie van plot_relationship_metadata SemPy.

    plot_relationship_metadata(suggested_relationships)
    

    Schermopname van relaties tussen tabellen in de gegevensset.

    Met de functie wordt de relatiehiërarchie aan de linkerkant aan de rechterkant beschreven, die overeenkomt met tabellen van 'van' en 'naar' in de uitvoer. Met andere woorden, de onafhankelijke 'from'-tabellen aan de linkerkant gebruiken hun refererende sleutels om te verwijzen naar hun 'naar'-afhankelijkheidstabellen aan de rechterkant. Elk entiteitsvak bevat kolommen die deelnemen aan de 'van' of 'naar'-kant van een relatie.

    Standaard worden relaties gegenereerd als 'm:1' (niet als '1:m') of '1:1'. De relaties 1:1 kunnen op een of beide manieren worden gegenereerd, afhankelijk van of de verhouding tussen toegewezen waarden en alle waarden in slechts één of beide richtingen coverage_threshold wordt overschreden. Verderop in deze zelfstudie behandelt u het minder frequente geval van 'm:m'-relaties.

Problemen met relatiedetectie oplossen

In het basislijnvoorbeeld ziet u een geslaagde relatiedetectie voor schone Synthea-gegevens . In de praktijk worden de gegevens zelden opgeschoond, waardoor succesvolle detectie wordt voorkomen. Er zijn verschillende technieken die nuttig kunnen zijn wanneer de gegevens niet worden opgeschoond.

In deze sectie van deze zelfstudie wordt de detectie van relaties opgelost wanneer het semantische model vuile gegevens bevat.

  1. Begin met het bewerken van de oorspronkelijke DataFrames om 'vuile' gegevens te verkrijgen en de grootte van de vuile gegevens af te drukken.

    # 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. Ter vergelijking: afdrukgrootten van de oorspronkelijke tabellen:

    print(len(patients))
    print(len(providers))
    
  3. Zoek relaties tussen de tabellen met behulp van de functie van SemPy find_relationships :

    find_relationships([patients_dirty, providers_dirty, encounters])
    

    In de uitvoer van de code ziet u dat er geen relaties zijn gedetecteerd vanwege de fouten die u eerder hebt geïntroduceerd om het semantische model 'vuil' te maken.

Validatie gebruiken

Validatie is het beste hulpprogramma voor het oplossen van fouten in relatiedetectie, omdat:

  • Het rapporteert duidelijk waarom een bepaalde relatie niet aan de regels voor refererende sleutels wordt gevolgd en daarom niet kan worden gedetecteerd.
  • Het wordt snel uitgevoerd met grote semantische modellen, omdat deze zich alleen richt op de gedeclareerde relaties en geen zoekopdracht uitvoert.

Validatie kan elk DataFrame gebruiken met kolommen die vergelijkbaar zijn met de kolommen die zijn gegenereerd door find_relationships. In de volgende code verwijst het suggested_relationships DataFrame naar patients in plaats patients_dirtyvan , maar u kunt de DataFrames aliasen met een woordenlijst:

dirty_tables = {
    "patients": patients_dirty,
    "providers" : providers_dirty,
    "encounters": encounters
}

errors = list_relationship_violations(dirty_tables, suggested_relationships)
errors

Losse zoekcriteria

In meer duistere scenario's kunt u proberen uw zoekcriteria los te maken. Deze methode verhoogt de kans op fout-positieven.

  1. Instellen include_many_to_many=True en evalueren of dit helpt:

    find_relationships(dirty_tables, include_many_to_many=True, coverage_threshold=1)
    

    De resultaten laten zien dat de relatie van encounters naar is patients gedetecteerd, maar er zijn twee problemen:

    • De relatie geeft een richting aan van patients naar encounters, wat een omgekeerde van de verwachte relatie is. Dit komt doordat alles patients is gedekt encounters door (Coverage From is 1,0) terwijl encounters slechts gedeeltelijk wordt gedekt door patients (Coverage To = 0,85), omdat patiëntenrijen ontbreken.
    • Er is een onbedoelde overeenkomst op een kolom met lage kardinaliteit GENDER , die overeenkomt met naam en waarde in beide tabellen, maar het is geen 'm:1'-relatie van belang. De lage kardinaliteit wordt aangegeven door Unique Count From en Unique Count To kolommen.
  2. Voer find_relationships opnieuw uit om alleen te zoeken naar 'm:1'-relaties, maar met een lagere coverage_threshold=0.5:

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

    Het resultaat toont de juiste richting van de relaties van encounters tot providers. De relatie van encounters naar patients wordt echter niet gedetecteerd, omdat patients deze niet uniek is, dus deze kan niet aan de 'een'-kant van de relatie 'm:1' staan.

  3. Los zowel include_many_to_many=True coverage_threshold=0.5als :

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

    Nu zijn beide relaties van belang zichtbaar, maar er is veel meer ruis:

    • De lage kardinaliteitsmatch GENDER is aanwezig.
    • Er wordt een hogere kardinaliteit 'm:m' ORGANIZATION weergegeven, waardoor het duidelijk is dat ORGANIZATION een kolom die niet is genormaliseerd voor beide tabellen.

Kolomnamen vergelijken

SemPy beschouwt standaard als overeenkomsten met alleen kenmerken die overeenkomen met naamovereenkomsten, waarbij ze profiteren van het feit dat databaseontwerpers meestal gerelateerde kolommen op dezelfde manier noemen. Dit gedrag helpt bij het voorkomen van valse relaties, die het vaakst voorkomen met gehele getallen met een lage kardinaliteit. Als er bijvoorbeeld productcategorieën en 1,2,3,...,10 orderstatuscode zijn1,2,3,...,10, worden ze met elkaar verward wanneer alleen waardetoewijzingen worden bekeken zonder rekening te houden met kolomnamen. Valse relaties mogen geen probleem zijn met GUID-achtige sleutels.

SemPy kijkt naar een overeenkomst tussen kolomnamen en tabelnamen. De overeenkomst is bij benadering en niet hoofdlettergevoelig. De subtekenreeksen van de decorator worden genegeerd, zoals 'id', 'code', 'name', 'key', 'pk', 'fk'. Als gevolg hiervan zijn de meest voorkomende overeenkomstcases:

  • een kenmerk met de naam 'kolom' in entiteit 'foo' komt overeen met een kenmerk met de naam 'column' (ook 'COLUMN' of 'Column') in de entiteit 'bar'.
  • een kenmerk met de naam 'kolom' in entiteit 'foo' komt overeen met een kenmerk met de naam 'column_id' in 'bar'.
  • een kenmerk met de naam 'bar' in entiteit 'foo' komt overeen met een kenmerk met de naam 'code' in 'bar'.

Door eerst de kolomnamen te vergelijken, wordt de detectie sneller uitgevoerd.

  1. Overeenkomen met de kolomnamen:

    • Als u wilt weten welke kolommen zijn geselecteerd voor verdere evaluatie, gebruikt u de verbose=2 optie (verbose=1 alleen de entiteiten die worden verwerkt).
    • De name_similarity_threshold parameter bepaalt hoe kolommen worden vergeleken. De drempelwaarde van 1 geeft aan dat u alleen geïnteresseerd bent in een overeenkomst van 100%.
    find_relationships(dirty_tables, verbose=2, name_similarity_threshold=1.0);
    

    Bij een overeenkomst van 100% kan geen rekening worden gehouden met kleine verschillen tussen namen. In uw voorbeeld hebben de tabellen een meervoudsvorm met achtervoegsel 's', wat resulteert in geen exacte overeenkomst. Dit is goed afgehandeld met de standaard name_similarity_threshold=0.8.

  2. Opnieuw uitvoeren met de standaardwaarde name_similarity_threshold=0.8:

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

    U ziet dat de id voor het meervoudformulier patients nu wordt vergeleken met de enkelvoud patient zonder te veel andere valse vergelijkingen toe te voegen aan de uitvoeringstijd.

  3. Opnieuw uitvoeren met de standaardwaarde name_similarity_threshold=0:

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

    Overstappen op name_similarity_threshold 0 is het andere extreme en geeft aan dat u alle kolommen wilt vergelijken. Dit is zelden nodig en resulteert in een verhoogde uitvoeringstijd en valse overeenkomsten die moeten worden gecontroleerd. Bekijk het aantal vergelijkingen in de uitgebreide uitvoer.

Overzicht van tips voor probleemoplossing

  1. Begin met exacte overeenkomst voor 'm:1'-relaties (dat wil zeggen, de standaard include_many_to_many=False en coverage_threshold=1.0). Dit is meestal wat u wilt.
  2. Gebruik een beperkte focus op kleinere subsets van tabellen.
  3. Gebruik validatie om problemen met gegevenskwaliteit te detecteren.
  4. Gebruik verbose=2 deze optie als u wilt weten welke kolommen in aanmerking komen voor relatie. Dit kan leiden tot een grote hoeveelheid uitvoer.
  5. Let op de afwegingen van zoekargumenten. include_many_to_many=True en coverage_threshold<1.0 kan ongewenste relaties produceren die moeilijker te analyseren zijn en moeten worden gefilterd.

Relaties detecteren op de volledige Synthea-gegevensset

Het eenvoudige basislijnvoorbeeld was een handig leer- en probleemoplossingsprogramma. In de praktijk kunt u beginnen met een semantisch model, zoals de volledige Synthea-gegevensset , die veel meer tabellen bevat. Verken de volledige synthea-gegevensset als volgt.

  1. Alle bestanden uit de map synthea/csv lezen:

    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. Zoek relaties tussen de tabellen met behulp van de functie van find_relationships SemPy:

    suggested_relationships = find_relationships(all_tables)
    suggested_relationships
    
  3. Relaties visualiseren:

    plot_relationship_metadata(suggested_relationships)
    

    Schermopname van de relaties tussen tabellen.

  4. Tel met hoeveel nieuwe 'm:m'-relaties worden gedetecteerd include_many_to_many=True. Deze relaties zijn naast de eerder getoonde 'm:1'-relaties; Daarom moet u filteren op multiplicity:

    suggested_relationships = find_relationships(all_tables, coverage_threshold=1.0, include_many_to_many=True) 
    suggested_relationships[suggested_relationships['Multiplicity']=='m:m']
    
  5. U kunt de relatiegegevens sorteren op verschillende kolommen om meer inzicht te krijgen in hun aard. U kunt er bijvoorbeeld voor kiezen om de uitvoer Row Count From te orden en Row Count To, waarmee u de grootste tabellen kunt identificeren.

    suggested_relationships.sort_values(['Row Count From', 'Row Count To'], ascending=False)
    

    In een ander semantisch model zou het misschien belangrijk zijn om te focussen op het aantal null-waarden Null Count From of Coverage To.

    Deze analyse kan u helpen te begrijpen of een van de relaties ongeldig kan zijn en of u ze uit de lijst met kandidaten moet verwijderen.

Bekijk andere zelfstudies voor semantische koppeling /SemPy: