บทช่วยสอน: ค้นหาความสัมพันธ์ใน ชุดข้อมูล Synthea โดยใช้ลิงก์แสดงความหมาย
บทช่วยสอนนี้แสดงวิธีการตรวจหาความสัมพันธ์ในชุดข้อมูล Synthea สาธารณะโดยใช้ลิงก์เชิงความหมาย
เมื่อคุณกําลังทํางานกับข้อมูลใหม่หรือทํางานโดยไม่มีแบบจําลองข้อมูลที่มีอยู่ จะเป็นประโยชน์ในการค้นหาความสัมพันธ์โดยอัตโนมัติ การตรวจหาความสัมพันธ์นี้สามารถช่วยให้คุณ:
- ทําความเข้าใจกับแบบจําลองในระดับสูง
- รับข้อมูลเชิงลึกเพิ่มเติมในระหว่างการวิเคราะห์ข้อมูลการสํารวจ
- ตรวจสอบข้อมูลที่อัปเดตแล้วหรือข้อมูลใหม่ ข้อมูลขาเข้า และ
- ทําความสะอาดข้อมูล
แม้ว่าความสัมพันธ์เป็นที่รู้จักล่วงหน้า การค้นหาความสัมพันธ์สามารถช่วยในการทําความเข้าใจเกี่ยวกับแบบจําลองข้อมูลหรือการระบุปัญหาคุณภาพของข้อมูลได้ดียิ่งขึ้น
ในบทช่วยสอนนี้ คุณเริ่มต้นด้วยตัวอย่างพื้นฐานอย่างง่ายที่คุณทดลองกับเพียงสามตารางเพื่อให้การเชื่อมต่อระหว่างตารางเป็นเรื่องง่าย จากนั้นคุณแสดงตัวอย่างที่ซับซ้อนมากขึ้นด้วยชุดตารางที่ใหญ่กว่า
ในบทช่วยสอนนี้ คุณจะเรียนรู้วิธีการ:
- ใช้คอมโพเนนต์ของไลบรารี Python ของลิงก์เชิงความหมาย (SemPy) ที่สนับสนุนการผสานรวมกับ Power BI และช่วยในการวิเคราะห์ข้อมูลโดยอัตโนมัติ คอมโพเนนต์เหล่านี้ประกอบด้วย:
- FabricDataFrame - โครงสร้างที่คล้ายกับ pandas เพิ่มขึ้นด้วยข้อมูลความหมายเพิ่มเติม
- ฟังก์ชันสําหรับการดึงแบบจําลองความหมายจากพื้นที่ทํางาน Fabric ลงในสมุดบันทึกของคุณ
- ฟังก์ชันที่ทําให้การค้นพบและการแสดงภาพของความสัมพันธ์ในแบบจําลองความหมายของคุณเป็นแบบอัตโนมัติ
- แก้ไขปัญหากระบวนการของการค้นพบความสัมพันธ์สําหรับแบบจําลองความหมายที่มีหลายตารางและการขึ้นต่อกัน
ข้อกำหนดเบื้องต้น
รับการสมัครใช้งาน Microsoft Fabric หรือลงทะเบียนเพื่อทดลองใช้งาน Microsoft Fabric ฟรี
ลงชื่อเข้าใช้ Microsoft Fabric
ใช้ตัวสลับประสบการณ์ทางด้านซ้ายของโฮมเพจของคุณเพื่อสลับไปยังประสบการณ์วิทยาศาสตร์ข้อมูล Synapse
- เลือก พื้นที่ทํางาน จากบานหน้าต่างนําทางด้านซ้ายเพื่อค้นหาและเลือกพื้นที่ทํางานของคุณ พื้นที่ทํางานนี้จะกลายเป็นพื้นที่ทํางานปัจจุบันของคุณ
ติดตามในสมุดบันทึก
สมุดบันทึก relationships_detection_tutorial.ipynb มาพร้อมกับบทช่วยสอนนี้
เมื่อต้องการเปิดสมุดบันทึกที่มาพร้อมกับบทช่วยสอนนี้ ให้ทําตามคําแนะนําใน เตรียมระบบของคุณสําหรับบทช่วยสอนวิทยาศาสตร์ข้อมูล เพื่อนําเข้าสมุดบันทึกไปยังพื้นที่ทํางานของคุณ
ถ้าคุณต้องการคัดลอกและวางรหัสจากหน้านี้แทน คุณสามารถสร้าง สมุดบันทึกใหม่ได้
ตรวจสอบให้แน่ใจว่าแนบ lakehouse เข้ากับสมุดบันทึก ก่อนที่คุณจะเริ่มเรียกใช้รหัส
ตั้งค่าสมุดบันทึก
ในส่วนนี้ คุณตั้งค่าสภาพแวดล้อมของสมุดบันทึกด้วยโมดูลและข้อมูลที่จําเป็น
ติดตั้ง
SemPy
จาก PyPI โดยใช้%pip
ความสามารถในการติดตั้งในบรรทัดภายในสมุดบันทึก:%pip install semantic-link
ทําการนําเข้าโมดูล SemPy ที่จําเป็นต่อมา:
import pandas as pd from sempy.samples import download_synthea from sempy.relationships import ( find_relationships, list_relationship_violations, plot_relationship_metadata )
นําเข้า pandas สําหรับการบังคับใช้ตัวเลือกการกําหนดค่าที่ช่วยในการจัดรูปแบบผลลัพธ์:
import pandas as pd pd.set_option('display.max_colwidth', None)
ดึงข้อมูลตัวอย่าง สําหรับบทช่วยสอนนี้ คุณใช้ ชุดข้อมูล Synthea ของเวชระเบียนสังเคราะห์ (เวอร์ชันขนาดเล็กเพื่อความง่าย):
download_synthea(which='small')
ตรวจจับความสัมพันธ์บนชุดย่อยของ ตาราง Synthea ขนาดเล็ก
เลือกสามตารางจากชุดใหญ่กว่า:
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')
ค้นหาความสัมพันธ์ระหว่างตารางโดยใช้ฟังก์ชันของ
find_relationships
SemPy:suggested_relationships = find_relationships([patients, providers, encounters]) suggested_relationships
แสดงภาพความสัมพันธ์ DataFrame เป็นกราฟ โดยใช้ฟังก์ชันของ
plot_relationship_metadata
SemPyplot_relationship_metadata(suggested_relationships)
ฟังก์ชันจะวางลําดับชั้นความสัมพันธ์จากด้านซ้ายมือทางด้านขวาซึ่งสอดคล้องกับตาราง "จาก" และ "ไปยัง" ในผลลัพธ์ กล่าวอีกนัยหนึ่ง ตารางอิสระ "จาก" ทางด้านซ้ายมือใช้คีย์นอกของตารางเพื่อชี้ไปยังตารางที่ขึ้นต่อกัน "ไปยัง" ทางด้านขวา แต่ละกล่องเอนทิตีแสดงคอลัมน์ที่เข้าร่วมในด้าน "จาก" หรือ "ไปยัง" ของความสัมพันธ์
ตามค่าเริ่มต้น ความสัมพันธ์จะถูกสร้างขึ้นเป็น "m:1" (ไม่ใช่เป็น "1:m") หรือ "1:1" ความสัมพันธ์ "1:1" สามารถสร้างได้หนึ่งหรือทั้งสองวิธี ขึ้นอยู่กับว่าอัตราส่วนของค่าที่แมปกับค่าทั้งหมดเกิน
coverage_threshold
เพียงหนึ่งทิศทางหรือทั้งสองทิศทาง ต่อมาในบทช่วยสอนนี้ คุณจะครอบคลุมกรณีที่พบได้บ่อยน้อยกว่าของความสัมพันธ์ "m:m"
แก้ไขปัญหาการตรวจหาความสัมพันธ์
ตัวอย่างพื้นฐานแสดงการตรวจหาความสัมพันธ์ที่ประสบความสําเร็จในการทําความสะอาดข้อมูล Synthea ในทางปฏิบัติ ข้อมูลไม่สะอาดซึ่งป้องกันการตรวจหาที่สําเร็จ มีหลายเทคนิคที่จะเป็นประโยชน์เมื่อข้อมูลไม่สะอาด
ส่วนนี้ของบทช่วยสอนนี้จะกล่าวถึงการตรวจหาความสัมพันธ์เมื่อแบบจําลองความหมายประกอบด้วยข้อมูลสกปรก
เริ่มต้นโดยการจัดการ 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))
สําหรับการเปรียบเทียบ ขนาดการพิมพ์ของตารางต้นฉบับ:
print(len(patients)) print(len(providers))
ค้นหาความสัมพันธ์ระหว่างตารางโดยใช้ฟังก์ชันของ
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
เกณฑ์การค้นหาที่คลาย
ในสถานการณ์ที่น่าขบขันมากขึ้น คุณสามารถลองคลายเกณฑ์การค้นหาของคุณได้ วิธีนี้จะเพิ่มความเป็นไปได้ของผลบวกเท็จ
ตั้งค่า
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
- ความสัมพันธ์แสดงทิศทางจาก
โปรดลอง
find_relationships
ค้นหาเฉพาะความสัมพันธ์ "m:1" แต่ด้วย ที่ต่ํากว่าcoverage_threshold=0.5
:find_relationships(dirty_tables, include_many_to_many=False, coverage_threshold=0.5)
ผลลัพธ์แสดงทิศทางที่ถูกต้องของความสัมพันธ์จาก
encounters
ไปยังproviders
อย่างไรก็ตาม ไม่มีการตรวจพบความสัมพันธ์จากencounters
ถึง เนื่องจากpatients
patients
ไม่ได้เป็นค่าเฉพาะ ดังนั้นจึงไม่สามารถอยู่ในด้าน "หนึ่ง" ของความสัมพันธ์ "m:1" ได้คลายทั้ง
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'
การตรวจหาจะทํางานได้เร็วขึ้นโดยการจับคู่ชื่อคอลัมน์ก่อน
ตรงกับชื่อคอลัมน์:
- เมื่อต้องการทําความเข้าใจว่าคอลัมน์ใดที่ถูกเลือกสําหรับการประเมินเพิ่มเติม ให้ใช้
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
- เมื่อต้องการทําความเข้าใจว่าคอลัมน์ใดที่ถูกเลือกสําหรับการประเมินเพิ่มเติม ให้ใช้
รีรันด้วย ค่าเริ่มต้น
name_similarity_threshold=0.8
:find_relationships(dirty_tables, verbose=2, name_similarity_threshold=0.8);
โปรดสังเกตว่า Id สําหรับฟอร์ม
patients
พหูพจน์จะถูกเปรียบเทียบกับเอกพจน์patient
โดยไม่ต้องเพิ่มการเปรียบเทียบอื่น ๆ มากมายไปยังเวลาการดําเนินการรีรันด้วย ค่าเริ่มต้น
name_similarity_threshold=0
:find_relationships(dirty_tables, verbose=2, name_similarity_threshold=0);
การเปลี่ยน
name_similarity_threshold
เป็น 0 เป็นค่าอื่นที่ร้ายแรงที่สุด และแสดงว่าคุณต้องการเปรียบเทียบคอลัมน์ทั้งหมด ซึ่งไม่ค่อยจําเป็นและส่งผลให้เวลาการดําเนินการเพิ่มขึ้นและการจับคู่ที่น่าแปลกใจที่จะต้องได้รับการตรวจสอบ สังเกตจํานวนการเปรียบเทียบในผลลัพธ์แบบอย่างละเอียด
ข้อมูลสรุปของเคล็ดลับการแก้ไขปัญหา
- เริ่มต้นจากการจับคู่ที่ตรงกันสําหรับความสัมพันธ์ "m:1" (นั่นคือ ค่าเริ่มต้น
include_many_to_many=False
และcoverage_threshold=1.0
) นี่คือสิ่งที่คุณต้องการ - ใช้โฟกัสแบบแคบบนชุดย่อยของตารางที่มีขนาดเล็กกว่า
- ใช้การตรวจสอบความถูกต้องเพื่อตรวจหาปัญหาคุณภาพของข้อมูล
- ใช้
verbose=2
ถ้าคุณต้องการทําความเข้าใจว่าคอลัมน์ใดที่จะถูกพิจารณาสําหรับความสัมพันธ์ ซึ่งอาจส่งผลให้มีเอาต์พุตจํานวนมาก - ระวังการซื้อขายของอาร์กิวเมนต์การค้นหา
include_many_to_many=True
และcoverage_threshold<1.0
อาจสร้างความสัมพันธ์ที่น่าสงสารซึ่งอาจยากต่อการวิเคราะห์และจะต้องถูกกรอง
ตรวจหาความสัมพันธ์บนชุดข้อมูล Synthea เต็มรูปแบบ
ตัวอย่างพื้นฐานอย่างง่ายคือเครื่องมือการเรียนรู้และการแก้ไขปัญหาที่สะดวก ในทางปฏิบัติ คุณอาจเริ่มต้นจากแบบจําลองความหมาย เช่น ชุดข้อมูล Synthea แบบเต็ม ซึ่งมีตารางเพิ่มเติมมากมาย สํารวจชุดข้อมูล synthea เต็มรูปแบบดังนี้
อ่านไฟล์ทั้งหมดจาก ไดเรกทอรี 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'), }
ค้นหาความสัมพันธ์ระหว่างตาราง โดยใช้ฟังก์ชันของ
find_relationships
SemPy:suggested_relationships = find_relationships(all_tables) suggested_relationships
แสดงภาพความสัมพันธ์:
plot_relationship_metadata(suggested_relationships)
นับจํานวนความสัมพันธ์ใหม่ "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']
คุณสามารถเรียงลําดับข้อมูลความสัมพันธ์ตามคอลัมน์ต่าง ๆ เพื่อให้เข้าใจลักษณะของคอลัมน์ได้ลึกซึ้งขึ้น ตัวอย่างเช่น คุณสามารถเลือกที่จะจัดลําดับเอาต์พุตโดย
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: