Автор оригинала: 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.