Вступление
XML (Extensible Markup Language) - это язык разметки, используемый для хранения структурированных данных. Библиотека анализа данных Pandas предоставляет функции для чтения / записи данных для большинства типов файлов.
Например, он включает read_csv()
и to_csv()
для взаимодействия с
файлами CSV. Однако Pandas не включает никаких методов для чтения и
записи файлов XML.
В этой статье мы рассмотрим, как мы можем использовать другие модули для чтения данных из XML-файла и загрузки их в Pandas DataFrame. Мы также возьмем данные из Pandas DataFrame и запишем их в файл XML.
Чтение XML с помощью Pandas
Давайте рассмотрим несколько способов чтения данных XML и их помещения в фрейм данных Pandas.
В этом разделе мы будем использовать один набор входных данных для
каждого скрипта. Сохраните следующий XML-код в файле с именем
properties.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<bathrooms>
<n35237 type="number">1.0</n35237>
<n32238 type="number">3.0</n32238>
<n44699 type="number">nan</n44699>
</bathrooms>
<price>
<n35237 type="number">7020000.0</n35237>
<n32238 type="number">10000000.0</n32238>
<n44699 type="number">4128000.0</n44699>
</price>
<property_id>
<n35237 type="number">35237.0</n35237>
<n32238 type="number">32238.0</n32238>
<n44699 type="number">44699.0</n44699>
</property_id>
</root>
Чтение с помощью xml.etree.ElementTree
Модуль xml.etree.ElementTree
встроен в Python. Он предоставляет
функциональные возможности для синтаксического анализа и создания
XML-документов. ElementTree
представляет XML-документ в виде дерева.
Мы можем перемещаться по документу, используя узлы, которые являются
элементами и подэлементами XML-файла.
В этом подходе мы читаем содержимое файла в переменной и используем
ET.XML()
для синтаксического анализа XML-документа на основе строковой
константы. Мы будем перебирать каждого дочернего и дочернего элементов,
поддерживая список данных, которые они содержат. Между тем, написание
дочерних тегов для столбца DataFrame. Затем мы записываем эти данные в
DataFrame.
Примечание. При чтении данных из XML мы должны транспонировать DataFrame, поскольку подэлементы списка данных записываются в столбцы.
Давайте посмотрим на код, чтобы продемонстрировать использование
xml.etree.ElementTree
:
import xml.etree.ElementTree as ET
import pandas as pd
xml_data = open('properties.xml', 'r').read() # Read file
root = ET.XML(xml_data) # Parse XML
data = []
cols = []
for i, child in enumerate(root):
data.append([subchild.text for subchild in child])
cols.append(child.tag)
df = pd.DataFrame(data).T # Write in DF and transpose it
df.columns = cols # Update column names
print(df)
Приведенный выше код будет производить такой вывод (зависит от используемого входного файла):
bathrooms price property_id
0 1.0 7020000.0 35237.0
1 3.0 10000000.0 32238.0
2 nan 4128000.0 44699.0
Чтение с lxml
Библиотека lxml
представляет собой привязку Python для библиотек C
libxml2
и libxslt
. Он также расширяет собственный модуль
ElementTree
Поскольку это сторонний модуль, вам нужно установить его с
помощью pip
следующим образом:
$ pip install lxml
В отличие от ElementTree
, мы не читаем данные файла и не анализируем
их. Мы можем напрямую использовать objectify.parse()
и указать ему
путь к XML-файлу. Чтобы получить корневой элемент, мы будем использовать
getroot()
для проанализированных данных XML.
Теперь мы можем перебрать дочерние элементы корневого узла и записать их в список Python. Как и раньше, мы создадим DataFrame, используя список данных, и транспонируем DataFrame.
Давайте посмотрим на код для создания Pandas DataFrame с использованием
lxml
:
from lxml import objectify
import pandas as pd
xml_data = objectify.parse('properties.xml') # Parse XML data
root = xml_data.getroot() # Root element
data = []
cols = []
for i in range(len(root.getchildren())):
child = root.getchildren()[i]
data.append([subchild.text for subchild in child.getchildren()])
cols.append(child.tag)
df = pd.DataFrame(data).T # Create DataFrame and transpose it
df.columns = cols # Update column names
print(df)
Если мы запустим это в интерпретаторе Python, мы увидим следующий результат:
bathrooms price property_id
0 1.0 7020000.0 35237.0
1 3.0 10000000.0 32238.0
2 nan 4128000.0 44699.0
Чтение с помощью xmltodict
Модуль xmltodict
преобразует данные XML в словарь Python, как следует
из названия. Как и lxml
, это сторонний модуль, который нам нужно
установить с помощью pip
:
$ pip install xmltodict
Как и раньше, мы считываем содержимое XML в переменную. Мы передаем эти
данные в parse()
который возвращает словарь XML-данных. Это будет
вложенный словарь, содержащий элементы и подэлементы XML-файла. Мы можем
перебрать элементы и записать их в список данных, который мы используем
для создания DataFrame.
Давайте посмотрим на код для анализа XML-данных для создания DataFrame с помощью xmltodict :
import xmltodict
import pandas as pd
xml_data = open('properties.xml', 'r').read() # Read data
xmlDict = xmltodict.parse(xml_data) # Parse XML
cols = xmlDict['root'].keys()
data = []
for i in xmlDict['root']:
child = xmlDict['root'][i]
data.append([child[subchild]['#text'] for subchild in child])
df = pd.DataFrame(data).T # Create DataFrame and transpose it.
df.columns = cols
print(df)
Если мы запустим приведенный выше код, мы увидим результат как:
bathrooms price property_id
0 1.0 7020000.0 35237.0
1 3.0 10000000.0 32238.0
2 nan 4128000.0 44699.0
Примечание . Библиотеку xmltodict
не рекомендуется использовать
для огромных файлов XML, поскольку многие разработчики наблюдали падение
производительности. Библиотека lxml
считается самой быстрой при работе
с XML, даже быстрее, чем включенный xml.etree.ElementTree
.
Используйте то, что лучше всего подходит для вашего проекта, а если производительность критична, вы должны запускать тесты с каждой библиотекой.
Написание XML с помощью Pandas
Давайте рассмотрим различные способы записи Pandas DataFrame в файл XML. Каждый сценарий, который мы используем ниже, создаст новый файл с именемordinates.xml со следующим содержимым:
<root>
<A>
<X>1.3</X>
<Y>2.6</Y>
<Z>2.1</Z>
</A>
<B>
<X>1.4</X>
<Y>1.4</Y>
<Z>5.6</Z>
</B>
<C>
<X>5.2</X>
<Y>4.6</Y>
<Z>4.6</Z>
</C>
</root>
Написание с помощью встроенной функции write ()
Мы можем использовать включенную write()
для файлов, чтобы записать
DataFrame как файл XML. Для этого мы будем вести список XML-данных,
чтобы каждый элемент представлял строку в XML. Затем мы переберем
DataFrame и запишем данные с соответствующими открывающими и
закрывающими тегами XML в список данных.
После этого мы перебираем список еще раз, чтобы записать данные в
XML-файл. Вот код, показывающий использование write()
:
import pandas as pd
df = pd.DataFrame([[1.3, 1.4, 5.2],
[2.6, 1.4, 4.6],
[2.1, 5.6, 4.6]],
columns=['A', 'B', 'C'],
index=['X', 'Y', 'Z'])
xml_data = ['<root>']
for column in df.columns:
xml_data.append('<{}>'.format(column)) # Opening element tag
for field in df.index:
# writing sub-elements
xml_data.append('<{0}>{1}</{0}>'.format(field, df[column][field]))
xml_data.append('</{}>'.format(column)) # Closing element tag
xml_data.append('</root>')
with open('coordinates.xml', 'w') as f: # Writing in XML file
for line in xml_data:
f.write(line)
Выполнение этого кода будет создать файл с именем coordinates.xml в текущем каталоге.
Написание файлов XML с помощью xml.etree.ElementTree
Модуль xml.etree.ElementTree
умолчанию можно использовать для хранения
данных в формате XML и преобразования их в строку, чтобы ее можно было
записать в файл.
Наш первый шаг - создать корневой элемент. Затем мы перебираем столбцы и
строки DataFrame, добавляя их как элементы и подэлементы в ElementTree.
Затем мы конвертируем ElementTree
в двоичную строку с помощью
tostring()
.
Поскольку данные XML представляют собой двоичную строку, мы декодируем ее в UTF-8 перед записью в файл.
Следующий код использует xml.etree.ElementTree
для записи DataFrame в
виде файла XML:
import xml.etree.ElementTree as ET
import pandas as pd
df = pd.DataFrame([[1.3, 1.4, 5.2],
[2.6, 1.4, 4.6],
[2.1, 5.6, 4.6]],
columns=['A', 'B', 'C'],
index=['X', 'Y', 'Z'])
header = df.columns
root = ET.Element('root') # Root element
for column in df.columns:
entry = ET.SubElement(root, column) # Adding element
for row in df.index:
schild = row
child = ET.SubElement(entry, schild) # Adding sub-element
child.text = str(df[column][schild])
xml_data = ET.tostring(root) # binary string
with open('coordinates.xml', 'w') as f: # Write in file as utf-8
f.write(xml_data.decode('utf-8'))
Как и раньше, запуск этого сценария создаст файл координат.xml с ожидаемым результатом.
Написание файлов XML с помощью lxml
Использование lxml
аналогично тому, как мы использовали
xml.etree.ElementTree
. Мы начинаем с создания etree
с корневым
элементом файла, который мы создаем. Затем мы перебираем DataFrame,
добавляя столбцы и строки как элементы и подэлементы дерева. Наконец, мы
используем метод tostring()
чтобы получить etree
в виде двоичной
строки. Записываем файл после декодирования двоичной строки в UTF-8.
Вот код для записи DataFrame как XML с использованием lxml:
from lxml import etree as et
import pandas as pd
root = et.Element('root') # Create root element
df = pd.DataFrame([[1.3, 1.4, 5.2],
[2.6, 1.4, 4.6],
[2.1, 5.6, 4.6]],
columns=['A', 'B', 'C'],
index=['X', 'Y', 'Z'])
for column in df.columns:
entry = et.SubElement(root, column) # Writing element
for row in df.index:
schild = row
child = et.SubElement(entry, schild) # Writing sub-elements
child.text = str(df[column][schild])
xml_data = et.tostring(root) # binary string
with open('coordinates.xml', 'w') as f: # Write in XML file as utf-8
f.write(xml_data.decode('utf-8'))
После успешного завершения, вы увидите coordinates.xml с координатами XML.
Заключение
В этом руководстве показаны различные способы чтения и записи XML-данных
с помощью Pandas DataFrames. Вы можете читать данные с помощью
встроенного xml.etree.ElementTree
, а также двух сторонних модулей:
lxml
и xmltodict
.
Для написания панды DataFrame в файл XML, мы использовали обычный файл
write()
со списками, в xml.etree.ElementTree
модуле и lxml
.
Учитывая, что непосредственное манипулирование строками XML для записи
файла более подвержено человеческим ошибкам, xml.etree.ElementTree
и
lxml
являются предпочтительными решениями для экспорта DataFrame в
XML.