Получение уникальных пар элементов в XML-файле с использованием Python - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть набор данных XML, который сконструирован так:

<DataSet>
    <Record><!-- each DataSet can have zero to many Record tags -->
        <Identifier><!-- each Record will definitely have exactly one Identifier tag -->
            <MRN value="MRN"></MRN><!-- Each Identifier will have zero or at the most one MRN tag, with alphanumeric character as the patient's MRN in value attribute -->
        </Identifier>
        <Medication><!-- each Record will definitely have exactly one Medication tag -->
            <Item value="CUI"></Item><!-- Each Medication will have zero to many Item tags, with alphanumeric character as the Medication CUI in the value attribute -->
        </Medication>
    </Record>
</DataSet>

И я хочу экспортировать список уникальных пар значений MRN / значений CUI в файл CSV. Конечный файл CSV будет выглядеть примерно так: два столбца:

enter image description here

Если у MRN более одного CUI, то я хочу, чтобы значение MRN повторялось в первом столбце для каждого CUI. Кроме того, мне не нужны пустые значения, то есть я не хочу извлекать MRN, которые не имеют CUI или наоборот.

Я пытался работать со списками и словарями, но проблема в том, что я не могу получить конечный вывод, чтобы он выглядел так, как я хочу, с повторением значения MRN для каждого CUI. Я даже создал фрейм данных, чтобы увидеть, какой CUI принадлежит какому MRN, но, опять же, это не тот вывод, который я хочу. Вот код, который я использовал:

import pandas as pd
import xml.etree.ElementTree as ET
tree = ET.parse('/med/dataset.xml')
root = tree.getroot()


mrn = []
cui = []
for element in root:
    for item in element[0::2]:
        d=[]
        mrn.append(d)
        for child in item:
            d.append(child.attrib['value'])
    for item in element[1::2]:
        d=[]
        cui.append(d)
        for child in item:
            d.append(child.attrib['value'])
new_list = [a + b for a,b in zip(mrn, cui)]
print(new_list)
df = pd.DataFrame(new_list)
print(df)

Я хочу сделать это, используя только стандартные библиотеки Python (pandas, numpy, xml.etree.ElementTree и csv).

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вы можете использовать ElementTree для анализа XML, сохранить комбинации mrn / cui в наборе, а затем создать CSV с помощью CSV.

Вот пример ...

XML Input (dataset.xml)

<DataSet>
    <Record>
        <Identifier>
            <MRN value="MRN1"></MRN>
        </Identifier>
        <Medication>
            <Item value="CUI1"></Item>
            <Item value="CUI2"></Item>
            <Item value="CUI3"></Item>
        </Medication>
    </Record>
    <Record>
        <Identifier>
            <MRN value="MRN1"></MRN>
        </Identifier>
        <Medication>
            <Item value="CUI1"></Item>
            <Item value="CUI2"></Item>
            <Item value="CUI3"></Item>
        </Medication>
    </Record>
    <Record>
        <Identifier>
            <MRN value="MRN2"></MRN>
        </Identifier>
        <Medication>
            <Item value="CUI1"></Item>
            <Item value="CUI2"></Item>
            <Item value="CUI3"></Item>
        </Medication>
    </Record>
</DataSet>

Python

import csv
import xml.etree.ElementTree as ET

tree = ET.parse("dataset.xml")

mrn_cui = set()

for record in tree.findall(".//Record"):
    mrn = record.find("./Identifier/MRN")
    items = record.findall("./Medication/Item")
    if mrn is not None and items:
        for cui in items:
            mrn_cui.add(f"{mrn.attrib['value']}|{cui.attrib['value']}")

with open("test.csv", "w", newline="") as csvfile:
    csvwriter = csv.writer(csvfile, delimiter=",", quoting=csv.QUOTE_MINIMAL)
    csvwriter.writerow(["MRN", "CUI"])
    for entry in sorted(mrn_cui):
        csvwriter.writerow(entry.split('|'))

Вывод (test.csv)

MRN,CUI
MRN1,CUI1
MRN1,CUI2
MRN1,CUI3
MRN2,CUI1
MRN2,CUI2
MRN2,CUI3

Вы также можете немного упростить его, используя lxml вместо ElementTree ...

Python

import csv
from lxml import etree

tree = etree.parse("dataset.xml")

mrn_cui = set()

for record in tree.xpath(".//Record[Identifier/MRN/@value and Medication/Item/@value]"):
    mrn = record.xpath("./Identifier/MRN/@value")
    for cui in record.xpath("./Medication/Item/@value"):
        mrn_cui.add(f"{mrn[0]}|{cui}")

with open("test.csv", "w", newline="") as csvfile:
    csvwriter = csv.writer(csvfile, delimiter=",", quoting=csv.QUOTE_MINIMAL)
    csvwriter.writerow(["MRN", "CUI"])
    for entry in sorted(mrn_cui):
        csvwriter.writerow(entry.split('|'))
0 голосов
/ 20 ноября 2018

Вы можете просто перебирать лекарства внутри своей петли через MRN. Попробуйте что-то вроде этого.

mrn_li = []
cui_li = []
for record in root:
    for mrn in record[0]:
        for med in record[1]:
            mrn_li.append(mrn.attrib['value'])
            cui_li.append(med.attrib['value'])

new_list = [[i, j] for i, j in zip(mrn_li,cui_li)]
print new_list
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...