แชร์ผ่าน


บทช่วยสอน: ค้นหาความสัมพันธ์ใน ชุดข้อมูล Synthea โดยใช้ลิงก์แสดงความหมาย

บทช่วยสอนนี้แสดงวิธีการตรวจหาความสัมพันธ์ในชุดข้อมูล Synthea สาธารณะโดยใช้ลิงก์เชิงความหมาย

เมื่อคุณกําลังทํางานกับข้อมูลใหม่หรือทํางานโดยไม่มีแบบจําลองข้อมูลที่มีอยู่ จะเป็นประโยชน์ในการค้นหาความสัมพันธ์โดยอัตโนมัติ การตรวจหาความสัมพันธ์นี้สามารถช่วยให้คุณ:

  • ทําความเข้าใจกับแบบจําลองในระดับสูง
  • รับข้อมูลเชิงลึกเพิ่มเติมในระหว่างการวิเคราะห์ข้อมูลการสํารวจ
  • ตรวจสอบข้อมูลที่อัปเดตแล้วหรือข้อมูลใหม่ ข้อมูลขาเข้า และ
  • ทําความสะอาดข้อมูล

แม้ว่าความสัมพันธ์เป็นที่รู้จักล่วงหน้า การค้นหาความสัมพันธ์สามารถช่วยในการทําความเข้าใจเกี่ยวกับแบบจําลองข้อมูลหรือการระบุปัญหาคุณภาพของข้อมูลได้ดียิ่งขึ้น

ในบทช่วยสอนนี้ คุณเริ่มต้นด้วยตัวอย่างพื้นฐานอย่างง่ายที่คุณทดลองกับเพียงสามตารางเพื่อให้การเชื่อมต่อระหว่างตารางเป็นเรื่องง่าย จากนั้นคุณแสดงตัวอย่างที่ซับซ้อนมากขึ้นด้วยชุดตารางที่ใหญ่กว่า

ในบทช่วยสอนนี้ คุณจะเรียนรู้วิธีการ:

  • ใช้คอมโพเนนต์ของไลบรารี Python ของลิงก์เชิงความหมาย (SemPy) ที่สนับสนุนการผสานรวมกับ Power BI และช่วยในการวิเคราะห์ข้อมูลโดยอัตโนมัติ คอมโพเนนต์เหล่านี้ประกอบด้วย:
    • FabricDataFrame - โครงสร้างที่คล้ายกับ pandas เพิ่มขึ้นด้วยข้อมูลความหมายเพิ่มเติม
    • ฟังก์ชันสําหรับการดึงแบบจําลองความหมายจากพื้นที่ทํางาน Fabric ลงในสมุดบันทึกของคุณ
    • ฟังก์ชันที่ทําให้การค้นพบและการแสดงภาพของความสัมพันธ์ในแบบจําลองความหมายของคุณเป็นแบบอัตโนมัติ
  • แก้ไขปัญหากระบวนการของการค้นพบความสัมพันธ์สําหรับแบบจําลองความหมายที่มีหลายตารางและการขึ้นต่อกัน

ข้อกำหนดเบื้องต้น

  • เลือก พื้นที่ทํางาน จากบานหน้าต่างนําทางด้านซ้ายเพื่อค้นหาและเลือกพื้นที่ทํางานของคุณ พื้นที่ทํางานนี้จะกลายเป็นพื้นที่ทํางานปัจจุบันของคุณ

ติดตามในสมุดบันทึก

สมุดบันทึก relationships_detection_tutorial.ipynb มาพร้อมกับบทช่วยสอนนี้

เมื่อต้องการเปิดสมุดบันทึกที่มาพร้อมกับบทช่วยสอนนี้ ให้ทําตามคําแนะนําใน เตรียมระบบของคุณสําหรับบทช่วยสอนวิทยาศาสตร์ข้อมูล เพื่อนําเข้าสมุดบันทึกไปยังพื้นที่ทํางานของคุณ

ถ้าคุณต้องการคัดลอกและวางรหัสจากหน้านี้แทน คุณสามารถสร้าง สมุดบันทึกใหม่ได้

ตรวจสอบให้แน่ใจว่าแนบ lakehouse เข้ากับสมุดบันทึก ก่อนที่คุณจะเริ่มเรียกใช้รหัส

ตั้งค่าสมุดบันทึก

ในส่วนนี้ คุณตั้งค่าสภาพแวดล้อมของสมุดบันทึกด้วยโมดูลและข้อมูลที่จําเป็น

  1. ติดตั้ง SemPy จาก PyPI โดยใช้ %pip ความสามารถในการติดตั้งในบรรทัดภายในสมุดบันทึก:

    %pip install semantic-link
    
  2. ทําการนําเข้าโมดูล SemPy ที่จําเป็นต่อมา:

    import pandas as pd
    
    from sempy.samples import download_synthea
    from sempy.relationships import (
        find_relationships,
        list_relationship_violations,
        plot_relationship_metadata
    )
    
  3. นําเข้า pandas สําหรับการบังคับใช้ตัวเลือกการกําหนดค่าที่ช่วยในการจัดรูปแบบผลลัพธ์:

    import pandas as pd
    pd.set_option('display.max_colwidth', None)
    
  4. ดึงข้อมูลตัวอย่าง สําหรับบทช่วยสอนนี้ คุณใช้ ชุดข้อมูล Synthea ของเวชระเบียนสังเคราะห์ (เวอร์ชันขนาดเล็กเพื่อความง่าย):

    download_synthea(which='small')
    

ตรวจจับความสัมพันธ์บนชุดย่อยของ ตาราง Synthea ขนาดเล็ก

  1. เลือกสามตารางจากชุดใหญ่กว่า:

    • patients ระบุข้อมูลผู้ป่วย
    • encounters ระบุผู้ป่วยที่พบแพทย์ (เช่น การนัดหมายแพทย์ ขั้นตอน)
    • providers ระบุผู้ให้บริการทางการแพทย์ที่เข้าร่วมกับผู้ป่วย

    ตาราง encounters ช่วยแก้ไขความสัมพันธ์แบบกลุ่มต่อกลุ่มระหว่าง patients และ providers และสามารถอธิบายได้ว่าเป็น เอนทิตี้ที่เกี่ยวข้อง:

    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. ค้นหาความสัมพันธ์ระหว่างตารางโดยใช้ฟังก์ชันของ find_relationships SemPy:

    suggested_relationships = find_relationships([patients, providers, encounters])
    suggested_relationships
    
  3. แสดงภาพความสัมพันธ์ DataFrame เป็นกราฟ โดยใช้ฟังก์ชันของ plot_relationship_metadata SemPy

    plot_relationship_metadata(suggested_relationships)
    

    สกรีนช็อตแสดงความสัมพันธ์ระหว่างตารางในชุดข้อมูล

    ฟังก์ชันจะวางลําดับชั้นความสัมพันธ์จากด้านซ้ายมือทางด้านขวาซึ่งสอดคล้องกับตาราง "จาก" และ "ไปยัง" ในผลลัพธ์ กล่าวอีกนัยหนึ่ง ตารางอิสระ "จาก" ทางด้านซ้ายมือใช้คีย์นอกของตารางเพื่อชี้ไปยังตารางที่ขึ้นต่อกัน "ไปยัง" ทางด้านขวา แต่ละกล่องเอนทิตีแสดงคอลัมน์ที่เข้าร่วมในด้าน "จาก" หรือ "ไปยัง" ของความสัมพันธ์

    ตามค่าเริ่มต้น ความสัมพันธ์จะถูกสร้างขึ้นเป็น "m:1" (ไม่ใช่เป็น "1:m") หรือ "1:1" ความสัมพันธ์ "1:1" สามารถสร้างได้หนึ่งหรือทั้งสองวิธี ขึ้นอยู่กับว่าอัตราส่วนของค่าที่แมปกับค่าทั้งหมดเกิน coverage_threshold เพียงหนึ่งทิศทางหรือทั้งสองทิศทาง ต่อมาในบทช่วยสอนนี้ คุณจะครอบคลุมกรณีที่พบได้บ่อยน้อยกว่าของความสัมพันธ์ "m:m"

แก้ไขปัญหาการตรวจหาความสัมพันธ์

ตัวอย่างพื้นฐานแสดงการตรวจหาความสัมพันธ์ที่ประสบความสําเร็จในการทําความสะอาดข้อมูล Synthea ในทางปฏิบัติ ข้อมูลไม่สะอาดซึ่งป้องกันการตรวจหาที่สําเร็จ มีหลายเทคนิคที่จะเป็นประโยชน์เมื่อข้อมูลไม่สะอาด

ส่วนนี้ของบทช่วยสอนนี้จะกล่าวถึงการตรวจหาความสัมพันธ์เมื่อแบบจําลองความหมายประกอบด้วยข้อมูลสกปรก

  1. เริ่มต้นโดยการจัดการ DataFrames ต้นฉบับเพื่อให้ได้ข้อมูล "สกปรก" และพิมพ์ขนาดของข้อมูลสกปรก

    # 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. สําหรับการเปรียบเทียบ ขนาดการพิมพ์ของตารางต้นฉบับ:

    print(len(patients))
    print(len(providers))
    
  3. ค้นหาความสัมพันธ์ระหว่างตารางโดยใช้ฟังก์ชันของ find_relationships SemPy:

    find_relationships([patients_dirty, providers_dirty, encounters])
    

    ผลลัพธ์ของโค้ดแสดงว่าไม่มีการตรวจพบความสัมพันธ์เนื่องจากข้อผิดพลาดที่คุณแนะนําก่อนหน้านี้เพื่อสร้างแบบจําลองเชิงความหมาย "สกปรก"

ใช้การตรวจสอบความถูกต้อง

การตรวจสอบความถูกต้องเป็นเครื่องมือที่ดีที่สุดสําหรับการแก้ไขปัญหาความล้มเหลวในการตรวจหาความสัมพันธ์เนื่องจาก:

  • ซึ่งจะรายงานอย่างชัดเจนว่าทําไมความสัมพันธ์เฉพาะไม่เป็นไปตามกฎของคีย์นอก ดังนั้นจึงไม่สามารถตรวจพบได้
  • ซึ่งทํางานได้อย่างรวดเร็วด้วยแบบจําลองความหมายขนาดใหญ่เนื่องจากจะมุ่งเน้นเฉพาะความสัมพันธ์ที่ประกาศและไม่ทําการค้นหา

การตรวจสอบความถูกต้องสามารถใช้ DataFrame ใด ๆ กับคอลัมน์ที่คล้ายกับคอลัมน์ที่สร้างขึ้นโดยfind_relationships ในโค้ด suggested_relationships ต่อไปนี้ DataFrame อ้างอิงถึง patients แทนที่จะ patients_dirtyเป็น แต่คุณสามารถนามแฝง DataFrames กับพจนานุกรม:

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

errors = list_relationship_violations(dirty_tables, suggested_relationships)
errors

เกณฑ์การค้นหาที่คลาย

ในสถานการณ์ที่น่าขบขันมากขึ้น คุณสามารถลองคลายเกณฑ์การค้นหาของคุณได้ วิธีนี้จะเพิ่มความเป็นไปได้ของผลบวกเท็จ

  1. ตั้งค่า include_many_to_many=True และประเมินถ้าจะช่วย:

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

    ผลลัพธ์แสดงให้เห็นว่าความสัมพันธ์จาก encounters ไปยัง patients ถูกตรวจพบ แต่มีปัญหาสองประการ:

    • ความสัมพันธ์แสดงทิศทางจาก patients ไปยัง encountersซึ่งเป็นค่าผกผันของความสัมพันธ์ที่คาดไว้ ทั้งนี้เนื่องจากทั้งหมด patients เกิดขึ้นโดย encounters (Coverage From คือ 1.0) ในขณะที่ encounters ถูกครอบคลุมเพียงบางส่วนโดย patients (Coverage To = 0.85) เนื่องจากแถวผู้ป่วยหายไป
    • มีรายการที่ตรงกันโดยไม่ได้ตั้งใจในคอลัมน์คาร์ดินาลลิตี้ GENDER ต่ํา ซึ่งเกิดขึ้นในการจับคู่ตามชื่อและค่าในทั้งสองตาราง แต่ไม่ใช่ความสัมพันธ์ของความสนใจแบบ "m:1" คาร์ดินาลลิตี้ต่ําจะแสดงโดยUnique Count Fromคอลัมน์ และUnique Count To
  2. โปรดลอง find_relationships ค้นหาเฉพาะความสัมพันธ์ "m:1" แต่ด้วย ที่ต่ํากว่า coverage_threshold=0.5:

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

    ผลลัพธ์แสดงทิศทางที่ถูกต้องของความสัมพันธ์จาก encounters ไปยังproviders อย่างไรก็ตาม ไม่มีการตรวจพบความสัมพันธ์จาก encounters ถึง เนื่องจากpatientspatientsไม่ได้เป็นค่าเฉพาะ ดังนั้นจึงไม่สามารถอยู่ในด้าน "หนึ่ง" ของความสัมพันธ์ "m:1" ได้

  3. คลายทั้ง include_many_to_many=True และ coverage_threshold=0.5:

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

    ในตอนนี้ ความสัมพันธ์ทั้งสองที่น่าสนใจจะมองเห็นได้ แต่มีเสียงรบกวนมากกว่า:

    • การจับคู่คาร์ดินาลลิตี้ต่ําปรากฏ GENDER อยู่
    • จํานวนสมาชิกในคาร์ดินาลลิตี้ที่สูงขึ้น "m:m" ORGANIZATION ตรงกันจะปรากฏขึ้น ทําให้เห็นได้ชัดว่า ORGANIZATION คอลัมน์จะถูกลดความซ้ําซ้อนในทั้งสองตาราง

จับคู่ชื่อคอลัมน์

ตามค่าเริ่มต้น SemPy จะพิจารณาว่าเป็นรายการที่ตรงกันเฉพาะแอตทริบิวต์ที่แสดงความคล้ายคลึงกันของชื่อ โดยการใช้ประโยชน์จากข้อเท็จจริงที่ผู้ออกแบบฐานข้อมูลมักจะตั้งชื่อคอลัมน์ที่เกี่ยวข้องด้วยวิธีเดียวกัน พฤติกรรมนี้จะช่วยหลีกเลี่ยงความสัมพันธ์ที่น่าสงสาร ซึ่งเกิดขึ้นบ่อยที่สุดกับคีย์จํานวนเต็มของคาร์ดินาลลิตี้ต่ํา ตัวอย่างเช่น ถ้ามี 1,2,3,...,10 หมวดหมู่ผลิตภัณฑ์และ 1,2,3,...,10 รหัสสถานะคําสั่งซื้อ พวกเขาจะสับสนเมื่อดูเฉพาะการแมปค่าโดยไม่ต้องใช้ชื่อคอลัมน์ลงในบัญชี ความสัมพันธ์ที่น่าแปลกใจไม่ควรมีปัญหากับคีย์ที่คล้ายกับ GUID

SemPy ดูที่ความคล้ายคลึงกันระหว่างชื่อคอลัมน์และชื่อตาราง การจับคู่จะเป็นการประมาณและไม่ตรงตามตัวพิมพ์ใหญ่-เล็ก จะละเว้นสตริงย่อยที่พบบ่อยที่สุดที่พบบ่อยที่สุด เช่น "id", "code", "name", "key", "pk", "fk" ผลที่ได้คือ กรณีการจับคู่ที่ใช้กันทั่วไปมากที่สุดคือ:

  • แอตทริบิวต์ที่เรียกว่า 'คอลัมน์' ในเอนทิตี 'foo' ตรงกับแอตทริบิวต์ที่เรียกว่า 'คอลัมน์' (และ 'COLUMN' หรือ 'Column') ในเอนทิตี 'bar'
  • แอตทริบิวต์ที่เรียกว่า 'คอลัมน์' ในเอนทิตี 'foo' ตรงกับแอตทริบิวต์ที่เรียกว่า 'column_id' ใน 'bar'
  • แอตทริบิวต์ที่เรียกว่า 'bar' ในเอนทิตี 'foo' ตรงกับแอตทริบิวต์ที่เรียกว่า 'โค้ด' ใน 'bar'

การตรวจหาจะทํางานได้เร็วขึ้นโดยการจับคู่ชื่อคอลัมน์ก่อน

  1. ตรงกับชื่อคอลัมน์:

    • เมื่อต้องการทําความเข้าใจว่าคอลัมน์ใดที่ถูกเลือกสําหรับการประเมินเพิ่มเติม ให้ใช้ verbose=2 ตัวเลือก (verbose=1 แสดงรายการเฉพาะเอนทิตีที่กําลังประมวลผล)
    • พารามิเตอร์ name_similarity_threshold กําหนดวิธีการเปรียบเทียบคอลัมน์ ค่าเกณฑ์ 1 แสดงว่าคุณสนใจจับคู่ 100% เท่านั้น
    find_relationships(dirty_tables, verbose=2, name_similarity_threshold=1.0);
    

    การทํางานที่ความคล้ายคลึงกัน 100% ล้มเหลวในการพิจารณาความแตกต่างเล็กน้อยระหว่างชื่อ ในตัวอย่างของคุณ ตารางมีรูปแบบพหูพจน์ที่มีคําต่อท้าย "s" ซึ่งส่งผลให้ไม่ตรงกันทั้งหมด ซึ่งจัดการได้ดีกับค่าเริ่มต้นname_similarity_threshold=0.8

  2. รีรันด้วย ค่าเริ่มต้น name_similarity_threshold=0.8:

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

    โปรดสังเกตว่า Id สําหรับฟอร์ม patients พหูพจน์จะถูกเปรียบเทียบกับเอกพจน์ patient โดยไม่ต้องเพิ่มการเปรียบเทียบอื่น ๆ มากมายไปยังเวลาการดําเนินการ

  3. รีรันด้วย ค่าเริ่มต้น name_similarity_threshold=0:

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

    การเปลี่ยน name_similarity_threshold เป็น 0 เป็นค่าอื่นที่ร้ายแรงที่สุด และแสดงว่าคุณต้องการเปรียบเทียบคอลัมน์ทั้งหมด ซึ่งไม่ค่อยจําเป็นและส่งผลให้เวลาการดําเนินการเพิ่มขึ้นและการจับคู่ที่น่าแปลกใจที่จะต้องได้รับการตรวจสอบ สังเกตจํานวนการเปรียบเทียบในผลลัพธ์แบบอย่างละเอียด

ข้อมูลสรุปของเคล็ดลับการแก้ไขปัญหา

  1. เริ่มต้นจากการจับคู่ที่ตรงกันสําหรับความสัมพันธ์ "m:1" (นั่นคือ ค่าเริ่มต้น include_many_to_many=False และ coverage_threshold=1.0) นี่คือสิ่งที่คุณต้องการ
  2. ใช้โฟกัสแบบแคบบนชุดย่อยของตารางที่มีขนาดเล็กกว่า
  3. ใช้การตรวจสอบความถูกต้องเพื่อตรวจหาปัญหาคุณภาพของข้อมูล
  4. ใช้ verbose=2 ถ้าคุณต้องการทําความเข้าใจว่าคอลัมน์ใดที่จะถูกพิจารณาสําหรับความสัมพันธ์ ซึ่งอาจส่งผลให้มีเอาต์พุตจํานวนมาก
  5. ระวังการซื้อขายของอาร์กิวเมนต์การค้นหา include_many_to_many=True และ coverage_threshold<1.0 อาจสร้างความสัมพันธ์ที่น่าสงสารซึ่งอาจยากต่อการวิเคราะห์และจะต้องถูกกรอง

ตรวจหาความสัมพันธ์บนชุดข้อมูล Synthea เต็มรูปแบบ

ตัวอย่างพื้นฐานอย่างง่ายคือเครื่องมือการเรียนรู้และการแก้ไขปัญหาที่สะดวก ในทางปฏิบัติ คุณอาจเริ่มต้นจากแบบจําลองความหมาย เช่น ชุดข้อมูล Synthea แบบเต็ม ซึ่งมีตารางเพิ่มเติมมากมาย สํารวจชุดข้อมูล synthea เต็มรูปแบบดังนี้

  1. อ่านไฟล์ทั้งหมดจาก ไดเรกทอรี 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. ค้นหาความสัมพันธ์ระหว่างตาราง โดยใช้ฟังก์ชันของ find_relationships SemPy:

    suggested_relationships = find_relationships(all_tables)
    suggested_relationships
    
  3. แสดงภาพความสัมพันธ์:

    plot_relationship_metadata(suggested_relationships)
    

    ภาพหน้าจอของความสัมพันธ์ระหว่างตาราง

  4. นับจํานวนความสัมพันธ์ใหม่ "m:m" ที่จะถูกค้นพบด้วยinclude_many_to_many=True ความสัมพันธ์เหล่านี้นอกเหนือจากความสัมพันธ์ที่แสดงไว้ก่อนหน้านี้ที่แสดงไว้ก่อนหน้านี้เป็น "m:1" ดังนั้น คุณจะต้องกรองข้อมูลบน multiplicity:

    suggested_relationships = find_relationships(all_tables, coverage_threshold=1.0, include_many_to_many=True) 
    suggested_relationships[suggested_relationships['Multiplicity']=='m:m']
    
  5. คุณสามารถเรียงลําดับข้อมูลความสัมพันธ์ตามคอลัมน์ต่าง ๆ เพื่อให้เข้าใจลักษณะของคอลัมน์ได้ลึกซึ้งขึ้น ตัวอย่างเช่น คุณสามารถเลือกที่จะจัดลําดับเอาต์พุตโดย Row Count From และ Row Count Toซึ่งช่วยระบุตารางที่ใหญ่ที่สุด

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

    ในแบบจําลองความหมายอื่น บางทีอาจเป็นสิ่งสําคัญที่ต้องมุ่งเน้นไปที่จํานวนของ null Null Count From หรือCoverage To

    การวิเคราะห์นี้สามารถช่วยให้คุณเข้าใจว่าความสัมพันธ์ใด ๆ อาจไม่ถูกต้องและหากคุณต้องการนําออกจากรายชื่อผู้สมัคร

ดูบทช่วยสอนอื่น ๆ สําหรับลิงก์ความหมาย / SemPy: