Python / Pandas / XML - 将 pandas 数据帧行写回 LXML
Python / Pandas / XML - Write pandas dataframe rows back to LXML
我目前正在使用 lxml 摄取一个 XML 文件,然后从根元素创建一个 pandas 数据框。我实际上是在使用 this example。我这样做是为了可以做一些数学运算/对数据进行一些建模。
下一步我想实现的是能够将数据写回 xml 文档。在我的脚本的其他地方,我使用了 root.insert
,因为我可以强制在特定位置索引处插入,以保持 xml 文档整洁和连贯。
有没有一种方法可以为数据帧中的每一行使用类似 root.insert(position, data)
的方式写出数据帧的每一行,其中数据帧列 header 是标签?
示例XML
<Root_Data>
<SomeData></SomeData>
<SomeOtherData></SomeOtherData>
<Weather>
<WxId>1</WxId>
<Temp>20></WxId>
<WindSpeed>15</WindSpeed>
</Weather>
# We will insert more weather here - I can find this position index. Assume it is 3.
<SomeMoreData></SomeMoreData>
<Root_Data>
Pandas 数据框:
ID Temp Windspeed
2 25 30
3 30 15
4 15 25
我会提供一些我到目前为止尝试过的代码 - 但实际上我空手而归如何将数据帧中的行插入到 xml 文档而无需手动构建 [=40] =] 作为字符串(不太好 - headers 可能会改变,这就是为什么我想使用列 headers 作为标签。)。
预期结果
<Root_Data>
<SomeData></SomeData>
<SomeOtherData></SomeOtherData>
<Weather>
<WxId>1</WxId>
<Temp>20></WxId>
<WindSpeed>15</WindSpeed>
</Weather>
<Weather>
<WxId>2</WxId>
<Temp>25></WxId>
<WindSpeed>30</WindSpeed>
</Weather>
<Weather>
<WxId>3</WxId>
<Temp>30></WxId>
<WindSpeed>15</WindSpeed>
</Weather>
<Weather>
<WxId>4</WxId>
<Temp>15></WxId>
<WindSpeed>25</WindSpeed>
</Weather>
<SomeMoreData></SomeMoreData>
<Root_Data>
到目前为止的示例代码:
from lxml import etree
import pandas as pd
tree = etree.parse('example.xml')
root = tree.getroot()
#Load into dataframe
for node in root:
res=[]
df_cols = ["WxId","Temp", "WindSpeed"]
res.append(node.attrib.get(df_cols[0]))
for el in df_cols[1:]:
if node is not None and node.find(el) is not None:
res.append(node.find(el).text)
else:
res.append(None)
rows.append({df_cols[i]: res[i]
for i, _ in enumerate(df_cols)})
out_df = pd.DataFrame(rows, columns = df_cols)
out_df = out_df[~out_df['Temp'].isnull()] #Proxy for good / bad data. Remove nulls.
#Now, write from data frame back to root so we can structure the XML before writing to file.
# ? Unknown method
您可以使用 to_xml
将数据帧转换为 xml:
xdata = df.rename(columns={'ID': 'WxId'})
.to_xml(index=False, root_name='Root_Data', row_name='Weather')
>>> xdata
<?xml version='1.0' encoding='utf-8'?>
<Root_Data>
<Weather>
<WxId>2</WxId>
<Temp>25</Temp>
<Windspeed>30</Windspeed>
</Weather>
<Weather>
<WxId>3</WxId>
<Temp>30</Temp>
<Windspeed>15</Windspeed>
</Weather>
<Weather>
<WxId>4</WxId>
<Temp>15</Temp>
<Windspeed>25</Windspeed>
</Weather>
</Root_Data>
现在您可以使用 lxml
在第一个子 Weather
和最后一个子 Weather
之前插入数据,或者在原始 xml 文件中的某处插入扩展数据。
仅供参考,您可以使用 pd.read_xml
将 xml 转换为数据帧。
另一种方法,以防您的列未定义或将来可能会增加。
df = pd.read_csv('./123.csv')
root = etree.Element("root")
for rows in range(0,df.shape[0]):
Tag = etree.Element('weather')
for cols in range(0,df.shape[1]):
etree.SubElement(Tag,df.iloc[rows:,cols].head().name).text = str(df.iloc[rows][cols])
# Append Element "Tag" to the Main Root here
root.append(Tag)
print(etree.tostring(root,encoding='Unicode'))
我目前正在使用 lxml 摄取一个 XML 文件,然后从根元素创建一个 pandas 数据框。我实际上是在使用 this example。我这样做是为了可以做一些数学运算/对数据进行一些建模。
下一步我想实现的是能够将数据写回 xml 文档。在我的脚本的其他地方,我使用了 root.insert
,因为我可以强制在特定位置索引处插入,以保持 xml 文档整洁和连贯。
有没有一种方法可以为数据帧中的每一行使用类似 root.insert(position, data)
的方式写出数据帧的每一行,其中数据帧列 header 是标签?
示例XML
<Root_Data>
<SomeData></SomeData>
<SomeOtherData></SomeOtherData>
<Weather>
<WxId>1</WxId>
<Temp>20></WxId>
<WindSpeed>15</WindSpeed>
</Weather>
# We will insert more weather here - I can find this position index. Assume it is 3.
<SomeMoreData></SomeMoreData>
<Root_Data>
Pandas 数据框:
ID Temp Windspeed
2 25 30
3 30 15
4 15 25
我会提供一些我到目前为止尝试过的代码 - 但实际上我空手而归如何将数据帧中的行插入到 xml 文档而无需手动构建 [=40] =] 作为字符串(不太好 - headers 可能会改变,这就是为什么我想使用列 headers 作为标签。)。
预期结果
<Root_Data>
<SomeData></SomeData>
<SomeOtherData></SomeOtherData>
<Weather>
<WxId>1</WxId>
<Temp>20></WxId>
<WindSpeed>15</WindSpeed>
</Weather>
<Weather>
<WxId>2</WxId>
<Temp>25></WxId>
<WindSpeed>30</WindSpeed>
</Weather>
<Weather>
<WxId>3</WxId>
<Temp>30></WxId>
<WindSpeed>15</WindSpeed>
</Weather>
<Weather>
<WxId>4</WxId>
<Temp>15></WxId>
<WindSpeed>25</WindSpeed>
</Weather>
<SomeMoreData></SomeMoreData>
<Root_Data>
到目前为止的示例代码:
from lxml import etree
import pandas as pd
tree = etree.parse('example.xml')
root = tree.getroot()
#Load into dataframe
for node in root:
res=[]
df_cols = ["WxId","Temp", "WindSpeed"]
res.append(node.attrib.get(df_cols[0]))
for el in df_cols[1:]:
if node is not None and node.find(el) is not None:
res.append(node.find(el).text)
else:
res.append(None)
rows.append({df_cols[i]: res[i]
for i, _ in enumerate(df_cols)})
out_df = pd.DataFrame(rows, columns = df_cols)
out_df = out_df[~out_df['Temp'].isnull()] #Proxy for good / bad data. Remove nulls.
#Now, write from data frame back to root so we can structure the XML before writing to file.
# ? Unknown method
您可以使用 to_xml
将数据帧转换为 xml:
xdata = df.rename(columns={'ID': 'WxId'})
.to_xml(index=False, root_name='Root_Data', row_name='Weather')
>>> xdata
<?xml version='1.0' encoding='utf-8'?>
<Root_Data>
<Weather>
<WxId>2</WxId>
<Temp>25</Temp>
<Windspeed>30</Windspeed>
</Weather>
<Weather>
<WxId>3</WxId>
<Temp>30</Temp>
<Windspeed>15</Windspeed>
</Weather>
<Weather>
<WxId>4</WxId>
<Temp>15</Temp>
<Windspeed>25</Windspeed>
</Weather>
</Root_Data>
现在您可以使用 lxml
在第一个子 Weather
和最后一个子 Weather
之前插入数据,或者在原始 xml 文件中的某处插入扩展数据。
仅供参考,您可以使用 pd.read_xml
将 xml 转换为数据帧。
另一种方法,以防您的列未定义或将来可能会增加。
df = pd.read_csv('./123.csv')
root = etree.Element("root")
for rows in range(0,df.shape[0]):
Tag = etree.Element('weather')
for cols in range(0,df.shape[1]):
etree.SubElement(Tag,df.iloc[rows:,cols].head().name).text = str(df.iloc[rows][cols])
# Append Element "Tag" to the Main Root here
root.append(Tag)
print(etree.tostring(root,encoding='Unicode'))