Стратегии тестирования метода Pandas read_xml()

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

В настоящее время инструменты ввода-вывода Pandas не поддерживают read_xml() и его аналог to_xml(). Однако read_json доказывает, что древовидные структуры могут быть реализованы для импорта фреймов данных и read_html для форматов разметки.

Если команда pandas рассматривает такой метод read_xml для будущей версии pandas, какую реализацию они бы выбрали? преследовать: синтаксический анализ с помощью встроенного xml.etree.ElementTree с его функциями iterfind() или iterparse() или сторонним модулем, lxml с его методами XPath 1.0 и XSLT 1.0?

Ниже приведены мои тестовые прогоны для четырех типов методов на простом, плоском, элементно-ориентированном вводе XML. Все настроены для обобщенного синтаксического анализа для любых дочерних элементов второго уровня root, и каждый метод должен давать точно такой же кадр данных pandas. Все, кроме последнего, вызывает pd.Dataframe() в списке словарей. Метод XSLT преобразует XML в CSV для преобразования StringIO() в pd.read_csv().

Question (составной)

  • ПРОИЗВОДИТЕЛЬНОСТЬ. Как вы объясните более медленный iterparse, часто рекомендуемый для больших файлов, поскольку файл анализируется итеративно? Отчасти это связано с логической проверкой if?

  • ПАМЯТЬ. Коррелирует ли память ЦП с таймингами в вызовах ввода-вывода? XSLT и XPath 1.0, как правило, плохо масштабируются с большими XML-документами, так как весь файл должен быть прочитан в памяти для анализа.

  • СТРАТЕГИЯ: Является ли список словарей оптимальной стратегией для Dataframe() вызов? Посмотрите эти интересные ответы: версия генератора и версия iterwalk, определяемая пользователем . Оба списка восходящего преобразования в фрейм данных.

Входные данные (текущие самые популярные пользователи по годам , включая наших друзей-панд)

<? xml version="1.0" encoding="utf-8"?> <stackoverflow> <topusers> <user>Гордон Линофф</user> <link>http://www.stackoverflow.com//users /1144035/gordon-linoff</link> <location>Нью-Йорк, США</location> <year_rep>5,985</year_rep> <total_rep>499,408</total_rep> <tag1>sql</ tag1> <tag2>sql-server</tag2> <tag3>mysql</tag3> </topusers> <topusers> <user>G√ºnter Z√∂chbauer</user> <link> http://www.stackoverflow.com//users/217408/g%c3%bcnter-z%c3%b6chbauer</link> <location>Линц, Австрия</location> <year_rep>5,835</year_rep> ; <total_rep>154,4 39</total_rep> <тег1>угловой2</тег1> <tag2>машинопись</tag2> <tag3>javascript</tag3> </топпользователи> <самые популярные пользователи> <пользователь>jezrael</user> <ссылка>http://www.stackoverflow.com//users/2901002/jezrael</link> <location>Братислава, Словакия</location> <year_rep>5740</year_rep> <total_rep>83 237</total_rep> <tag1>панды</tag1> <tag2>питон</tag2> <tag3>фрейм данных</tag3> </топпользователи> <самые популярные пользователи> <пользователь>VonC</user> <ссылка>http://www.stackoverflow.com//users/6309/vonc</link> <location>Франция</location> <year_rep>5577</year_rep> <total_rep>651 397</total_rep> <tag1>git</tag1> <tag2>github</tag2> <tag3>докер</tag3> </топпользователи> <самые популярные пользователи> <user>Мартейн Питерс</user> <ссылка>http://www.stackoverflow.com//users/100297/martijn-pieters</link> <location>Кембридж, Соединенное Королевство</location> <year_rep>5 337</year_rep> <total_rep>525 176</total_rep> <tag1>питон</tag1> <tag2>python-3.x</tag2> <tag3>python-2.7</tag3> </топпользователи> <самые популярные пользователи> <пользователь>TJ Краудер</пользователь> <ссылка>http://www.stackoverflow.com//users/157247/tj-crowder</link> <location>Великобритания</location> <year_rep>5 258</year_rep> <total_rep>508 310</total_rep> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>java</tag3> </топпользователи> <самые популярные пользователи> <пользователь>akrun</user> <ссылка>http://www.stackoverflow.com//users/3732271/akrun</link> <местоположение></местоположение> <year_rep>5 188</year_rep> <total_rep>229 553</total_rep> <tag1>r</tag1> <tag2>dplyr</tag2> <tag3>фрейм данных</tag3> </топпользователи> <самые популярные пользователи> <user>Виктор Стриби?ью</user> <link>http://www.stackoverflow.com//users/3832970/wiktor-stribi%c5%bcew</link> <location>Варшава, Польша</location> <year_rep>4948</year_rep> <total_rep>158 134</total_rep> <tag1>регулярное выражение</tag1> <tag2>javascript</tag2> <tag3>c#</tag3> </топпользователи> <самые популярные пользователи> <user>Дарин Димитров</user> <ссылка>http://www.stackoverflow.com//users/29407/darin-dimitrov</link> <location>София, Болгария</location> <year_rep>4936</year_rep> <total_rep>709 683</total_rep> <tag1>c#</tag1> <tag2>asp.net-mvc</tag2> <tag3>asp.net-mvc-3</tag3> </топпользователи> <самые популярные пользователи> <user>Эрик Думинил</user> <ссылка>http://www.stackoverflow.com//users/6419007/eric-duminil</link> <местоположение></местоположение> <year_rep>4854</year_rep> <total_rep>12 557</total_rep> <tag1>рубин</tag1> <tag2>ruby-on-rails</tag2> <tag3>массивы</tag3> </топпользователи> <самые популярные пользователи> <пользователь>alecxe</user> <ссылка>http://www.stackoverflow.com//users/771848/alecxe</link> <location>Нью-Йорк, США</location> <year_rep>4723</year_rep> <total_rep>233 368</total_rep> <tag1>питон</tag1> <tag2>селен</tag2> <tag3>транспортир</tag3> </топпользователи> <самые популярные пользователи> <user>Жан-Франсуа Фабр</user> <ссылка>http://www.stackoverflow.com//users/6451573/jean-fran%c3%a7ois-fabre</link> <location>Тулуза, Франция</location> <year_rep>4526</year_rep> <total_rep>30 027</total_rep> <tag1>питон</tag1> <tag2>python-3.x</tag2> <tag3>python-2.7</tag3> </топпользователи> <самые популярные пользователи> <пользователь>piRSquared</user> <ссылка>http://www.stackoverflow.com//users/2336654/pirsquared</link> <location>Белвью, Вашингтон, США</location> <year_rep>4482</year_rep> <total_rep>41 183</total_rep> <tag1>панды</tag1> <tag2>питон</tag2> <tag3>фрейм данных</tag3> </топпользователи> <самые популярные пользователи> <пользователь>CommonsWare</пользователь> <ссылка>http://www.stackoverflow.com//users/115145/commonsware</link> <location>Кто хочет знать?</location> <year_rep>4475</year_rep> <total_rep>616 135</total_rep> <tag1>для Android</tag1> <tag2>java</tag2> <tag3>намерение Android</tag3> </топпользователи> <самые популярные пользователи> <пользователь>Квентин</пользователь> <ссылка>http://www.stackoverflow.com//users/19068/quentin</link> <location>Великобритания</location> <year_rep>4464</year_rep> <total_rep>509 365</total_rep> <tag1>javascript</tag1> <tag2>html</tag2> <tag3>css</tag3> </топпользователи> <самые популярные пользователи> <user>Джон Скит</user> <ссылка>http://www.stackoverflow.com//users/22656/jon-skeet</link> <location>Рединг, Соединенное Королевство</location> <year_rep>4348</year_rep> <total_rep>921 690</total_rep> <tag1>c#</tag1> <tag2>java</tag2> <tag3>.net</tag3> </топпользователи> <самые популярные пользователи> <пользователь>Феликс Клинг</user> <ссылка>http://www.stackoverflow.com//users/218196/felix-kling</link> <location>Саннивейл, Калифорния</location> <year_rep>4324</year_rep> <total_rep>411 535</total_rep> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>асинхронный</tag3> </топпользователи> <самые популярные пользователи> <пользователь>мэтт</пользователь> <ссылка>http://www.stackoverflow.com//users/341994/matt</link> <местоположение></местоположение> <year_rep>4313</year_rep> <total_rep>220 515</total_rep> <tag1>свифт</tag1> <tag2>ios</tag2> <tag3>xcode</tag3> </топпользователи> <самые популярные пользователи> <пользователь>Psidom</пользователь> <ссылка>http://www.stackoverflow.com//users/4983450/psidom</link> <location>Атланта, Джорджия, США</location> <year_rep>4236</year_rep> <total_rep>36 950</total_rep> <tag1>питон</tag1> <tag2>панды</tag2> <tag3>r</tag3> </топпользователи> <самые популярные пользователи> <пользователь>Мартин Р</пользователь> <ссылка>http://www.stackoverflow.com//users/1187415/martin-r</link> <location>Германия</location> <year_rep>4195</year_rep> <total_rep>269 380</total_rep> <tag1>свифт</tag1> <tag2>ios</tag2> <tag3>swift3</tag3> </топпользователи> <самые популярные пользователи> <пользователь>Бармар</пользователь> <ссылка>http://www.stackoverflow.com//users/1491895/barmar</link> <location>Арлингтон, Массачусетс</location> <year_rep>4179</year_rep> <total_rep>289 989</total_rep> <tag1>javascript</tag1> <tag2>php</tag2> <tag3>jquery</tag3> </топпользователи> <самые популярные пользователи> <user>Алексей Мезенин</user> <ссылка>http://www.stackoverflow.com//users/1227923/alexey-mezenin</link> <местоположение>??????</местоположение> <year_rep>4 142</year_rep> <total_rep>31 602</total_rep> <tag1>ларавель</tag1> <tag2>php</tag2> <tag3>laravel-5.3</tag3> </топпользователи> <самые популярные пользователи> <пользователь>BalusC</user> <ссылка>http://www.stackoverflow.com//users/157882/balusc</link> <location>Амстердам, Нидерланды</location> <year_rep>4046</year_rep> <total_rep>703 046</total_rep> <tag1>java</tag1> <tag2>jsf</tag2> <tag3>сервлеты</tag3> </топпользователи> <самые популярные пользователи> <пользователь>ГурВ</пользователь> <ссылка>http://www.stackoverflow.com//users/6348498/gurv</link> <местоположение></местоположение> <year_rep>4016</year_rep> <total_rep>7932</total_rep> <tag1>sql</tag1> <tag2>mysql</tag2> <tag3>sql-сервер</tag3> </топпользователи> <самые популярные пользователи> <user>Нина Шольц</user> <ссылка>http://www.stackoverflow.com//users/1447675/nina-scholz</link> <location>Берлин, Германия</location> <year_rep>3950</year_rep> <total_rep>61 135</total_rep> <tag1>javascript</tag1> <tag2>массивы</tag2> <tag3>объект</tag3> </топпользователи> <самые популярные пользователи> <user>JB Nizet</user> <ссылка>http://www.stackoverflow.com//users/571407/jb-nizet</link> <location>Сент-Этьен, Франция</location> <year_rep>3923</year_rep> <total_rep>418 780</total_rep> <tag1>java</tag1> <tag2>спящий режим</tag2> <tag3>java-8</tag3> </топпользователи> <самые популярные пользователи> <user>Фрэнк ван Паффелен</user> <ссылка>http://www.stackoverflow.com//users/209103/frank-van-puffelen</link> <location>Сан-Франциско, Калифорния</location> <year_rep>3920</year_rep> <total_rep>86 520</total_rep> <tag1>firebase</tag1> <tag2>firebase-database</tag2> <tag3>для Android</tag3> </топпользователи> <самые популярные пользователи> <пользователь>dasblinkenlight</user> <ссылка>http://www.stackoverflow.com//users/335858/dasblinkenlight</link> <location>США</location> <year_rep>3886</year_rep> <total_rep>475 813</total_rep> <tag1>c#</tag1> <tag2>java</tag2> <tag3>С++</tag3> </топпользователи> <самые популярные пользователи> <user>Тим Бигеляйзен</user> <ссылка>http://www.stackoverflow.com//users/1863229/tim-biegeleisen</link> <location>Сингапур</location> <year_rep>3814</year_rep> <total_rep>77 211</total_rep> <tag1>sql</tag1> <tag2>mysql</tag2> <tag3>java</tag3> </топпользователи> <самые популярные пользователи> <user>Грег Хьюгилл</user> <ссылка>http://www.stackoverflow.com//users/893/greg-hewgill</link> <location>Крайстчерч, Новая Зеландия</location> <year_rep>3796</year_rep> <total_rep>529 137</total_rep> <tag1>git</tag1> <tag2>питон</tag2> <tag3>git-pull</tag3> </топпользователи> <самые популярные пользователи> <пользователь>unutbu</пользователь> <ссылка>http://www.stackoverflow.com//users/190597/unutbu</link> <местоположение></местоположение> <year_rep>3735</year_rep> <total_rep>401 595</total_rep> <tag1>питон</tag1> <tag2>панды</tag2> <tag3>нумпи</tag3> </топпользователи> <самые популярные пользователи> <user>Ханс Пассант</user> <ссылка>http://www.stackoverflow.com//users/17034/hans-passant</link> <location>Мэдисон, Висконсин</location> <year_rep>3688</year_rep> <total_rep>672 118</total_rep> <tag1>c#</tag1> <tag2>.net</tag2> <tag3>winforms</tag3> </топпользователи> <самые популярные пользователи> <user>Джонатан Леффлер</user> <ссылка>http://www.stackoverflow.com//users/15168/jonathan-leffler</link> <location>Калифорния, США</location> <year_rep>3649</year_rep> <total_rep>455 157</total_rep> <tag1>c</tag1> <tag2>bash</tag2> <tag3>unix</tag3> </топпользователи> <самые популярные пользователи> <пользователь>paxdiablo</user> <ссылка>http://www.stackoverflow.com//users/14860/paxdiablo</link> <местоположение></местоположение> <year_rep>3636</year_rep> <total_rep>507 043</total_rep> <tag1>c</tag1> <tag2>c++</tag2> <tag3>bash</tag3> </топпользователи> <самые популярные пользователи> <user>Пранав С. Балан</user> <ссылка>http://www.stackoverflow.com//users/3037257/pranav-c-balan</link> <location>Рамантали, Каннур, штат Керала, Индия</location> <year_rep>3604</year_rep> <total_rep>64 476</total_rep> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>html</tag3> </топпользователи> <самые популярные пользователи> <user>Сурагч</user> <ссылка>http://www.stackoverflow.com//users/3681880/suragch</link> <location>Хух-Хото, Китай</location> <year_rep>3580</year_rep> <total_rep>71 032</total_rep> <tag1>свифт</tag1> <tag2>ios</tag2> <tag3>для Android</tag3> </топпользователи> </переполнение стека> 

Методы Python

import xml.etree.ElementTree as et import pandas as pd from io import StringIO from lxml import etree as lxet def read_xml_iterfind(): tree = et.parse("Input.xml") data = [] inner = {} for el in tree.iterfind("./*"): for i in el.iterfind("* "): inner[i.tag] = i.text data.append(inner) inner = {} df = pd.DataFrame(data) def read_xml_iterparse(): data = [] inner = {} i = 1 for (ev , el) в et.iterparse(path): if i <= 2: first_tag = el.tag if el.tag == first_tag и len(inner) != 0: data.append(inner) inner = {} if el.text не равен None, а len(el.text.strip()) > 0: inner[el.tag] = el.text i += 1 df = pd.DataFrame(data) def read_xml_lxml_xpath(): tree = lxet.parse("Input.xml") data = [] inner = {} для el in tree.xpath("/*/*"): for i in el: inner[i.tag] = i.text data.append(inner) inner = {} df = pd.DataFrame(data) def read_xml_lxml_xsl( ): xml = lxet.parse("Ввод.xml") xslstr = """ <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output version="1.0" encoding= "UTF-8" indent="yes" method="text"/> <xsl:strip-space elements="*"/> <!-- ЗАГОЛОВКИ --> <xsl:template match = "/*"> <xsl:for-each select="*[1]/*"> <xsl:value-of select="local-name()" /> <xsl:choose> <xsl:when test="position() != last()"> <xsl:text>,</xsl:text> </xsl:when> <xsl:иначе> <xsl: text>&#xa;</xsl:text> </xsl:иначе> </xsl:choose> </xsl:for-each> <xsl:apply-templates/> </ xsl:template> <!-- СТРОКИ ДАННЫХ (ЧЕРЕЗ ЗАПЯТЫЕ) --> <xsl:template match="/*/*" priority="2"> <xsl:for-each select=" *"> <xsl:if test="position() = 1"> <xsl:text>&quot;</xsl:text> </xsl:if> <xsl:value- of select="." /> <xsl:choose> <xsl:when test="position() != last()"> <xsl:text>&quot;,& quot;</xsl:text> </xsl:когда> <xsl:иначе> <xsl:text>&quot;&#xa;</xsl:text> </xsl:иначе> </xsl:выбрать> </xsl:для каждого> </xsl:шаблон> </xsl:преобразование> """ xsl = lxet.fromstring(xslstr) transform = lxet.XSLT(xsl) newdom = transform(xml) df = pd.read_csv(StringIO(str(newdom))) 

Время (с текущим XML и XML с 25-кратным количеством дочерних элементов (т. е. 900 пользовательских записей StackOverflow)

# КОРОТКИЙ ФАЙЛ python -mtimeit -s"импортировать readxml_test_runs как тест" "test.read_xml_iterfind()" 100 циклов, лучший из 3: 3,87 мс на цикл python -mtimeit -s"импортировать readxml_test_runs как тест" "test.read_xml_iterparse()" 100 циклов, лучший из 3 : 5,5 мс на цикл python -mtimeit -s"импортировать readxml_test_runs как тест" "test.read_xml_lxml_xpath()" 100 циклов, лучшее из 3: 3,86 мс на цикл python -mtimeit -s"импортировать readxml_test_runs как тест" "test.read_xml_lxml_xsl( )" 100 циклов, лучший из 3: 5,68 мс на цикл # БОЛЬШОЙ ФАЙЛ python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_iterfind()" 100 циклов, лучший из 3: 36 мс на цикл python -mtimeit -n"100" -s"импортировать readxml_test_runs как тест" "test.read_xml_i terparse()" 100 циклов, лучший из 3: 78,9 мс на цикл python -mtimeit -n"100" -s"импорт readxml_test_runs как тест" "test.read_xml_lxml_xpath()" 100 циклов, лучший из 3: 32,7 мс на цикл python -mtimeit -n"100" -s"импортировать readxml_test_runs как тест" "test.read_xml_lxml_xsl()" 100 циклов, лучшее из 3: 51,4 мс на цикл