Рубрики
Без рубрики

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

В этой статье вы узнаете, как считывать данные из XML-файла и загружать их в фрейм данных Pandas. Вы также экспортируете данные из фрейма данных Pandas в XML-файл.

Автор оригинала: Naazneen Jatu.

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

Вступление

XML (Extensible Markup Language) – это язык разметки, используемый для хранения структурированных данных. Библиотека анализа данных Pandas предоставляет функции для чтения/записи данных для большинства типов файлов.

Например, он включает в себя read_csv() и to_csv() для взаимодействия с CSV-файлами. Однако Pandas не включает в себя никаких методов чтения и записи XML-файлов.

В этой статье мы рассмотрим, как мы можем использовать другие модули для чтения данных из XML-файла и загрузки их в фрейм данных Pandas. Мы также возьмем данные из фрейма данных Pandas и запишем их в XML-файл.

Чтение XML с помощью панд

Давайте рассмотрим несколько способов чтения XML-данных и помещаем их в фрейм данных Pandas.

В этом разделе мы будем использовать один набор входных данных для каждого сценария. Сохраните следующий XML-файл в файле с именем properties.xml :



	
		1.0
		3.0
		nan
	
	
		7020000.0
		10000000.0
		4128000.0
	
	
		35237.0
		32238.0
		44699.0
	

Чтение с помощью xml.etree.ElementTree

Файл xml.etree.Модуль ElementTree поставляется встроенным в Python. Он предоставляет функциональные возможности для синтаксического анализа и создания XML-документов. ElementTree представляет XML-документ в виде дерева. Мы можем перемещаться по документу, используя узлы, которые являются элементами и подэлементами XML-файла.

В этом подходе мы читаем содержимое файла в переменной и используем ET.XML() для синтаксического анализа XML-документа из строковой константы. Мы будем петлять по каждому дочернему и дочернему элементу, поддерживая список содержащихся в них данных. Тем временем, написание дочерних тегов для столбца фрейма данных. Затем мы записываем эти данные в фрейм данных.

Примечание: При чтении данных из XML мы должны транспонировать фрейм данных, так как подэлементы списков данных записываются в столбцы.

Давайте посмотрим на код, демонстрирующий использование 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. Как и раньше, мы создадим фрейм данных с помощью списка данных и транспонируем его.

Давайте посмотрим на код для создания фрейма данных Pandas с помощью 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-файла. Мы можем перебирать элементы и записывать их в список данных, который мы используем для создания фрейма данных.

Давайте посмотрим на код для анализа XML-данных для создания фрейма данных с помощью 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 в XML-файл. Каждый сценарий, который мы используем ниже, создаст новый файл с именем coordinates.xml со следующим содержанием:


  
    1.3
    2.6
    2.1
  
  
    1.4
    1.4
    5.6
  
  
    5.2
    4.6
    4.6
  

Мы можем использовать включенную функцию write() для файлов, чтобы записать фрейм данных в виде XML-файла. Для этого мы будем хранить список XML-данных таким образом, чтобы каждый элемент представлял собой строку в XML. Затем мы переберем фрейм данных и запишем данные с соответствующими открывающими и закрывающими тегами 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 = ['']
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}'.format(field, df[column][field]))
    xml_data.append(''.format(column))  # Closing element tag
xml_data.append('')

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 и преобразования их в строку, чтобы их можно было записать в файл.

Наш первый шаг-это создание корневого элемента. Затем мы перебираем столбцы и строки фрейма данных, добавляя их как элементы и подэлементы в дерево элементов. Затем мы преобразуем данные объекта ElementTree в двоичную строку с помощью метода tostring () .

Поскольку XML-данные представляют собой двоичную строку, мы декодируем ее в UTF-8 перед записью в файл.

Следующий код использует xml.etree.ElementTree для записи фрейма данных в виде 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'))

Как и раньше, запуск этого скрипта создаст coordinates.xml файл с ожидаемым результатом.

Написание XML-файлов с помощью lxml

Использование lxml аналогично тому, как мы использовали xml.etree.ElementTree . Мы начинаем с создания объекта etree с корневым элементом создаваемого файла. Затем мы перебираем фрейм данных, добавляя столбцы и строки в качестве элементов и подэлементов дерева. Наконец, мы используем метод 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. Вы можете читать данные с помощью встроенного xml.etree.Модуль ElementTree , а также два сторонних модуля: lxml и xmltodict .

Для записи фрейма данных Pandas в XML-файл мы использовали обычный файл write() со списками, файл xml.etree.ElementTree модуль и lxml . Учитывая, что манипулирование XML-строками непосредственно для записи файла более подвержено человеческой ошибке, xml.etree.ElementTree и lxml являются предпочтительными решениями для экспорта фрейма данных в XML.