Share 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 van semantische koppelingen (SemPy) 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.

Voorwaarden

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

Volg mee in het notitieblok

De notebook relationships_detection_tutorial.ipynb begeleidt deze zelfstudie.

Het notebook instellen

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

  1. Installeer 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ëntgegevens op
    • encounters geeft de patiënten aan die medische ontmoeting hadden (bijvoorbeeld een medische afspraak, procedure)
    • providers geeft aan welke medische dienstverleners zorg hebben verleend aan de patiënten

    De encounters tabel lost een veel-op-veel-relatie tussen patients en providers op en 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. Relaties tussen de tabellen zoeken met behulp van de find_relationships functie van SemPy:

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

    plot_relationship_metadata(suggested_relationships)
    

    Schermopname met relaties tussen tabellen in de gegevensset.

    De functie legt de relatiehiërarchie van links naar rechts uit, wat overeenkomt met de 'van' en 'naar' tabellen 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 groter is dan coverage_threshold. 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. Relaties tussen de tabellen zoeken met behulp van de find_relationships functie van SemPy:

    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 Foreign Keys voldoet en om deze reden 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 van patients_dirty, maar u kunt de DataFrames wel aliasen met een woordenlijst:

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

errors = list_relationship_violations(dirty_tables, suggested_relationships)
errors

Zoekcriteria versoepelen

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

  1. Stel include_many_to_many=True in en evalueer of dit helpt:

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

    De resultaten tonen aan dat de relatie tussen encounters en patients is gedetecteerd, maar er zijn twee problemen:

    • De relatie geeft een richting aan van patients tot encounters, wat een inverse van de verwachte relatie is. Dit komt doordat alle patients worden gedekt door encounters (Coverage From is 1,0) terwijl encounters slechts gedeeltelijk worden gedekt door patients (Coverage To = 0,85), omdat patiëntenrijen ontbreken.
    • Er is een onbedoelde overeenkomst op een lage cardinaliteit GENDER kolom, die overeenkomt qua naam en waarde in beide tabellen, maar het is geen 'm:1'-relatie van interesse. 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 tussen encounters en patients wordt echter niet gedetecteerd, omdat patients niet uniek is, zodat deze niet aan de 'een'-kant van 'm:1'-relatie kan staan.

  3. Maak zowel include_many_to_many=True als coverage_threshold=0.5los:

    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 op GENDER is aanwezig.
    • Er verscheen een 'm:m'-overeenkomst met een hogere kardinaliteit op ORGANIZATION, waaruit blijkt dat ORGANIZATION waarschijnlijk een kolom is die naar beide tabellen is gedenormaliseerd.

Kolomnamen vergelijken

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

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

  • 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 optie verbose=2 (verbose=1 alleen de entiteiten weergeeft die worden verwerkt).
    • De parameter name_similarity_threshold bepaalt hoe kolommen worden vergeleken. De drempelwaarde van 1 geeft aan dat u alleen geïnteresseerd bent in 100% wedstrijd.
    find_relationships(dirty_tables, verbose=2, name_similarity_threshold=1.0);
    

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

  2. Opnieuw uitvoeren met de standaard name_similarity_threshold=0.8:

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

    U ziet dat de id voor meervoudsvorm patients nu wordt vergeleken met enkelvoud patient zonder dat er te veel andere overbodige vergelijkingen aan de uitvoeringstijd worden toegevoegd.

  3. Opnieuw uitvoeren met de standaard name_similarity_threshold=0:

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

    Het wijzigen van name_similarity_threshold in 0 is het andere uiterst 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. Controleer 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 als u wilt weten welke kolommen in aanmerking komen voor relatie. Dit kan leiden tot een grote hoeveelheid output.
  5. Let op de afwegingen van zoekargumenten. include_many_to_many=True en coverage_threshold<1.0 kunnen valse 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 als volgt de volledige synthea gegevensset.

  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 find_relationships functie van 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 hoeveel nieuwe 'm:m'-relaties worden gedetecteerd met 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 te orden op Row Count From 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 is het misschien belangrijk 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 tutorials voor semantische koppeling / SemPy: