Чтение и запись файлов XML с помощью Pandas

Введение XML (Extensible Markup Language) - это язык разметки, используемый для хранения структурированных данных. Библиотека анализа данных Pandas предоставляет функции для чтения / записи данных для большинства типов файлов. Например, он включает read_csv () и to_csv () для взаимодействия с файлами CSV. Однако Pandas не включает никаких методов для чтения и записи файлов XML. В этой статье мы рассмотрим, как мы можем использовать другие модули для чтения данных из XML-файла и загрузки их в Pandas DataFrame. Мы будем

Вступление

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.

comments powered by Disqus