我有一个问题,关于如何通过基于它们的公共列遍历每个表中的所有字段来为某些关系数据框编写 XML 文档。
我有 3 个表,分别是入院、诊断和日常干预。这 3 个表通过公共列 adNo 相关联。我想导出每个广告号的所有相关记录
我导入了以下三个df
admission = pd.read_csv(r'Path where the CSV file is stored\File name.csv')
diagnosis = pd.read_csv(r'Path where the CSV file is stored\File name.csv')
dailyIntervention = pd.read_csv(r'Path where the CSV file is stored\File name.csv')
入场
广告否 | F姓名 | L名字 | D.O.B |
---|---|---|---|
2001 | 大卫 | 院长 | 23/04/1984 |
2002 | 约翰 | 雪 | 11/02/1988 |
2003 | 小子 | 杰夫 | 30/12/1987 |
诊断
descID | 描述 | 阅读代码 | adNo |
---|---|---|---|
2 | 细支气管炎 | XVGF | 2001 |
4 | 心肌病 | rtyu | 2001 |
6 | VSD | oiug | 2002 |
每日干预
内部ID | 活动日期 | 心电图 | 广告否 |
---|---|---|---|
100 | 02/03/2023 | 1 | 2001 |
101 | 04/02/2023 | 1 | 2001 |
102 | 03/02/2023 | 0 | 2001 |
103 | 02/02/2023 | 0 | 2002 |
104 | 05/02/2023 | 1 | 2003 |
我想将存在于admission数据框上的每个adNo的所有记录写入一个xml文件。
请看下面我想要的结果
<?xml version="1.0" encoding="UTF-8"?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2023-03-10T11:15:55">
<EpisodeDetails>
<Admission>
<adNo>2001</adNo>
<FName>David</FName>
<LName>Dean</LName>
<D.O.B>1984-04-23T00:00:00</D.O.B>
</Admission>
<diagnosis>
<dascID>2</dascID>
<description>BRONCHIOLITIS</description>
<readCode>XVGF</readCode>
<adNo>2001</adNo>
</diagnosis>
<diagnosis>
<dascID>4</dascID>
<description>CARDIOMYOPATHY</description>
<readCode>rtyu</readCode>
<adNo>2001</adNo>
</diagnosis>
<dailyIntervention>
<IntID>100</IntID>
<activitydate>2023-03-02T00:00:00</activitydate>
<ecg>1</ecg>
<adNo>2001</adNo>
</dailyIntervention>
<dailyIntervention>
<IntID>101</IntID>
<activitydate>2023-02-04T00:00:00</activitydate>
<ecg>1</ecg>
<adNo>2001</adNo>
</dailyIntervention>
<dailyIntervention>
<IntID>102</IntID>
<activitydate>2023-02-03T00:00:00</activitydate>
<ecg>0</ecg>
<adNo>2001</adNo>
</dailyIntervention>
</EpisodeDetails>
<EpisodeDetails>
<Admission>
<adNo>2002</adNo>
<FName>John</FName>
<LName>Snow</LName>
<D.O.B>1988-02-11T00:00:00</D.O.B>
</Admission>
<diagnosis>
<dascID>6</dascID>
<description>VSD</description>
<readCode>oiug</readCode>
<adNo>2002</adNo>
</diagnosis>
<dailyIntervention>
<IntID>103</IntID>
<activitydate>2023-02-02T00:00:00</activitydate>
<ecg>0</ecg>
<adNo>2002</adNo>
</dailyIntervention>
</EpisodeDetails>
<EpisodeDetails>
<Admission>
<adNo>2003</adNo>
<FName>Brat</FName>
<LName>Jeff</LName>
<D.O.B>1987-12-30T00:00:00</D.O.B>
</Admission>
<dailyIntervention>
<IntID>104</IntID>
<activitydate>2023-02-05T00:00:00</activitydate>
<ecg>1</ecg>
<adNo>2002</adNo>
</dailyIntervention>
</EpisodeDetails>
</dataroot>
你在这里完成的任务相当艰巨,但可以结合使用 pandas、lxml 和 f-strings 来完成。请注意,在您的实际 csvs 中,某些间距等可能与问题中的不同,但您可以根据需要进行调整。
主要构建块是一系列用于入院、诊断和日常干预部分的模板;然后将这些模板插入到各自的剧集详细信息容器中,然后将其插入到 XML 文档本身中。
其中一些可能会通过添加一两个辅助函数来简化,但恐怕我没有时间去尝试。
import pandas as pd
from lxml import etree
#the document skeleton
xml_string = """<?xml version="1.0" encoding="UTF-8"?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2023-03-10T11:15:55">
</dataroot>"""
doc = etree.XML(xml_string.encode())
#create the structure for each episode:
for a in admission['adNo']:
#create an episode container:
epi = etree.fromstring('<EpisodeDetails/>')
#get episode data
ad_det = admission[admission['adNo ']==a].to_csv(index=False, header=False).strip().split(',')
#use f-strings to insert the details into an Admission template
admit = f"""<Admission>
<adNo>{ad_det[0]}</adNo>
<FName>{ad_det[1]}</FName>
<LName>{ad_det[2]}</LName>
<D.O.B>{ad_det[3]}</D.O.B>
</Admission>"""
#insert this into the Episode container
epi.append(etree.fromstring(admit))
#repeat the process for the diagnosis section:
diags=diagnosis[diagnosis['adNo']==a].to_csv(index=False, header=False).strip().split('\r\n')
for d in range(len(diags)):
diag_det = diags[d].split(',')
if len(diag_det)==4:
#use the diagnosis template this time:
diagno = f"""<diagnosis>
<dascID>{diag_det[0]}</dascID>
<description>{diag_det[1]}</description>
<readCode>{diag_det[2]}</readCode>
<adNo>{diag_det[3]}</adNo>
</diagnosis>"""
epi.append(etree.fromstring(diagno))
#finally, do the same for daily interventions
intervs = dailyIntervention[dailyIntervention['adNo']==a].to_csv(index=False, header=False).strip().split('\r\n')
for d in range(len(intervs)):
interv_det = intervs[d].split(',')
if len(interv_det)==4:
daily_i =f""" <dailyIntervention>
<IntID>{interv_det[0]}</IntID>
<activitydate>{interv_det[1]}</activitydate>
<ecg>{interv_det[2]}</ecg>
<adNo>{interv_det[3]}</adNo>
</dailyIntervention>"""
epi.append(etree.fromstring(daily_i))
#now append the whole thing to the document itself
doc.append(epi)
#you need python 3.9 for this:
etree.indent(doc, space=' ')
print(etree.tostring(doc).decode())
输出应该是您的预期输出。
DataFrame.to_xml
方法获取部分 XML 结构,然后组合它们:
import re
from textwrap import indent
re_data = re.compile("</?data>\n?")
dfs = {"Admission": admission, "diagnosis": diagnosis, "dailyIntervention": dailyIntervention}
groups = {}
for name, df in dfs.items():
for adNo, sdf in df.groupby("adNo"):
if adNo not in groups:
groups[adNo] = ""
xml_str = sdf.to_xml(index=False, row_name=name, xml_declaration=False)
groups[adNo] += "\n" + re_data.sub("", xml_str).rstrip()
with open("result.xml", "w") as file:
file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
file.write('<dataroot>\n')
for group in groups.values():
xml_str = "<EpisodeDetails>" + group + "\n</EpisodeDetails>\n"
file.write(indent(xml_str, " "))
file.write("</dataroot>")
首先收集resp。字典中的数据帧,以所需的标签名称作为键。然后将每个数据帧按
adNo
分组(这里假设这是将数据帧粘合在一起的相关键)并通过.to_xml
将相应的XML结构提取到字符串中,删除与根相关的部分,并存储以adNo
为键的字典中的组合字符串。然后将各个部分连接在一起,嵌入到EpisodeDetails
标签中,并添加根级别。
如果您想要与预期输出中一样的确切日期时间格式,请转换 resp。预先列,例如:
admission["D.O.B"] = (
pd.to_datetime(admission["D.O.B"], dayfirst=True)
.dt.strftime("%Y-%m-%dT%H:%M:%S")
)