Panda’s read_xml() methodeteststrategieën

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

Momenteel onderhoudt pandas I/O-tools geen

code>read_xml() methode en de tegenhanger to_xml(). Echter, read_json bewijst dat boomachtige structuren kunnen worden geïmplementeerd voor het importeren van dataframes en read_html voor opmaakformaten.

Als het panda-team een dergelijke read_xml-methode overweegt voor een toekomstige panda-versie, welke implementatie zouden ze dan chase: ontleden met ingebouwde xml.etree.ElementTree met zijn iterfind() of iterparse() functies of de module van derden, lxml met zijn XPath 1.0- en XSLT 1.0-methoden?

Hieronder staan mijn testruns voor vier methodetypes op een eenvoudige, platte, elementgerichte XML-invoer. Ze zijn allemaal ingesteld voor gegeneraliseerde ontleding voor elk tweede niveau van root en elke methode zou exact hetzelfde panda-dataframe moeten opleveren. Alles behalve de laatste roept pd.Dataframe() aan in de lijst met woordenboeken. De XSLT-methode transformeert XML naar CSV voor gegoten StringIO() in pd.read_csv().

Vraag (meerdelige)

  • PRESTATIES: Hoe verklaart u de langzamere iterparse die vaak wordt aanbevolen voor grotere bestanden omdat het bestand iteratief wordt geparseerd? Is dit deels te wijten aan de if logische controles?

  • GEHEUGEN: correleert CPU-geheugen met timings in I/O-aanroepen? XSLT en XPath 1.0 schalen meestal niet goed met grotere XML-documenten, omdat het hele bestand in het geheugen moet worden gelezen om te worden geparseerd.

  • STRATEGIE: Is een lijst met woordenboeken een optimale strategie voor Dataframe() aanroepen? Zie deze interessante antwoorden: generator versie en een iterwalk door de gebruiker gedefinieerde versie . Beide upcast-lijsten naar dataframe.

Invoer Gegevens (Stack Overflow's huidige topgebruikers per jaar waaronder onze pandavrienden)

<? xml version="1.0" encoding="utf-8"?> <stackoverflow> <topusers> <user>Gordon Linoff</user> <link>http://www.stackoverflow.com//users /1144035/gordon-linoff</link> <location>New York, Verenigde Staten</location> <year_rep>5.985</year_rep> <total_rep>499.408</total_rep>/sql> <tag1< 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>Linz, Oostenrijk</location> <year_rep>5,835</year_rep> ; <total_rep>154,4 39</total_rep> <tag1>hoekig2</tag1> <tag2>typescript</tag2> <tag3>javascript</tag3> </topusers> <topusers> <user>jezrael</user> <link>http://www.stackoverflow.com//users/2901002/jezrael</link> <location>Bratislava, Slowakije</location> <year_rep>5,740</year_rep> <total_rep>83,237</total_rep> <tag1>panda's</tag1> <tag2>python</tag2> <tag3>dataframe</tag3> </topusers> <topusers> <user>VonC</user> <link>http://www.stackoverflow.com//users/6309/vonc</link> <locatie>Frankrijk</locatie> <year_rep>5.577</year_rep> <total_rep>651.397</total_rep> <tag1>git</tag1> <tag2>github</tag2> <tag3>docker</tag3> </topusers> <topusers> <user>Martijn Pieters</user> <link>http://www.stackoverflow.com//users/100297/martijn-pieters</link> <location>Cambridge, Verenigd Koninkrijk</location> <year_rep>5.337</year_rep> <total_rep>525,176</total_rep> <tag1>python</tag1> <tag2>python-3.x</tag2> <tag3>python-2.7</tag3> </topusers> <topusers> <gebruiker>TJ Crowder</gebruiker> <link>http://www.stackoverflow.com//users/157247/tj-crowder</link> <location>Verenigd Koninkrijk</location> <year_rep>5,258</year_rep> <total_rep>508.310</total_rep> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>java</tag3> </topusers> <topusers> <user>akrun</user> <link>http://www.stackoverflow.com//users/3732271/akrun</link> <locatie></locatie> <year_rep>5.188</year_rep> <total_rep>229,553</total_rep> <tag1>r</tag1> <tag2>dplyr</tag2> <tag3>dataframe</tag3> </topusers> <topusers> <user>Wiktor Stribi?ew</user> <link>http://www.stackoverflow.com//users/3832970/wiktor-stribi%c5%bcew</link> <location>Warschau, Polen</location> <year_rep>4.948</year_rep> <total_rep>158,134</total_rep> <tag1>regex</tag1> <tag2>javascript</tag2> <tag3>c#</tag3> </topusers> <topusers> <user>Darin Dimitrov</user> <link>http://www.stackoverflow.com//users/29407/darin-dimitrov</link> <location>Sofia, Bulgarije</location> <year_rep>4.936</year_rep> <total_rep>709,683</total_rep> <tag1>c#</tag1> <tag2>asp.net-mvc</tag2> <tag3>asp.net-mvc-3</tag3> </topusers> <topusers> <user>Eric Duminil</user> <link>http://www.stackoverflow.com//users/6419007/eric-duminil</link> <locatie></locatie> <year_rep>4.854</year_rep> <total_rep>12.557</total_rep> <tag1>robijn</tag1> <tag2>ruby-on-rails</tag2> <tag3>matrices</tag3> </topusers> <topusers> <user>alecxe</user> <link>http://www.stackoverflow.com//users/771848/alecxe</link> <locatie>New York, Verenigde Staten</locatie> <year_rep>4.723</year_rep> <total_rep>233.368</total_rep> <tag1>python</tag1> <tag2>selenium</tag2> <tag3>gradenboog</tag3> </topusers> <topusers> <user>Jean-Fran√ßois Fabre</user> <link>http://www.stackoverflow.com//users/6451573/jean-fran%c3%a7ois-fabre</link> <location>Toulouse, Frankrijk</location> <year_rep>4,526</year_rep> <total_rep>30,027</total_rep> <tag1>python</tag1> <tag2>python-3.x</tag2> <tag3>python-2.7</tag3> </topusers> <topusers> <user>piRSquared</user> <link>http://www.stackoverflow.com//users/2336654/pirsquared</link> <location>Bellevue, WA, Verenigde Staten</location> <year_rep>4.482</year_rep> <total_rep>41,183</total_rep> <tag1>panda's</tag1> <tag2>python</tag2> <tag3>dataframe</tag3> </topusers> <topusers> <user>CommonsWare</user> <link>http://www.stackoverflow.com//users/115145/commonsware</link> <location>Wie wil het weten?</location> <year_rep>4.475</year_rep> <total_rep>616,135</total_rep> <tag1>android</tag1> <tag2>java</tag2> <tag3>android-intent</tag3> </topusers> <topusers> <user>Quentin</user> <link>http://www.stackoverflow.com//users/19068/quentin</link> <location>Verenigd Koninkrijk</location> <year_rep>4.464</year_rep> <total_rep>509,365</total_rep> <tag1>javascript</tag1> <tag2>html</tag2> <tag3>css</tag3> </topusers> <topusers> <user>Jon Skeet</user> <link>http://www.stackoverflow.com//users/22656/jon-skeet</link> <location>Reading, Verenigd Koninkrijk</location> <year_rep>4.348</year_rep> <total_rep>921.690</total_rep> <tag1>c#</tag1> <tag2>java</tag2> <tag3>.net</tag3> </topusers> <topusers> <user>Felix Kling</user> <link>http://www.stackoverflow.com//users/218196/felix-kling</link> <location>Sunnyvale, CA</location> <year_rep>4.324</year_rep> <total_rep>411,535</total_rep> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>asynchroon</tag3> </topusers> <topusers> <user>matt</user> <link>http://www.stackoverflow.com//users/341994/matt</link> <locatie></locatie> <year_rep>4.313</year_rep> <total_rep>220,515</total_rep> <tag1>swift</tag1> <tag2>ios</tag2> <tag3>xcode</tag3> </topusers> <topusers> <user>Psidom</user> <link>http://www.stackoverflow.com//users/4983450/psidom</link> <location>Atlanta, GA, Verenigde Staten</location> <year_rep>4.236</year_rep> <total_rep>36.950</total_rep> <tag1>python</tag1> <tag2>panda's</tag2> <tag3>r</tag3> </topusers> <topusers> <user>Martin R</user> <link>http://www.stackoverflow.com//users/1187415/martin-r</link> <locatie>Duitsland</locatie> <year_rep>4.195</year_rep> <total_rep>269,380</total_rep> <tag1>swift</tag1> <tag2>ios</tag2> <tag3>swift3</tag3> </topusers> <topusers> <user>Barmar</user> <link>http://www.stackoverflow.com//users/1491895/barmar</link> <locatie>Arlington, MA</locatie> <year_rep>4.179</year_rep> <total_rep>289.989</total_rep> <tag1>javascript</tag1> <tag2>php</tag2> <tag3>jquery</tag3> </topusers> <topusers> <user>Alexey Mezenin</user> <link>http://www.stackoverflow.com//users/1227923/alexey-mezenin</link> <locatie>????</locatie> <year_rep>4,142</year_rep> <total_rep>31,602</total_rep> <tag1>laravel</tag1> <tag2>php</tag2> <tag3>laravel-5.3</tag3> </topusers> <topusers> <user>BalusC</user> <link>http://www.stackoverflow.com//users/157882/balusc</link> <locatie>Amsterdam, Nederland</locatie> <year_rep>4.046</year_rep> <total_rep>703.046</total_rep> <tag1>java</tag1> <tag2>jsf</tag2> <tag3>servlets</tag3> </topusers> <topusers> <user>GurV</user> <link>http://www.stackoverflow.com//users/6348498/gurv</link> <locatie></locatie> <year_rep>4.016</year_rep> <total_rep>7.932</total_rep> <tag1>sql</tag1> <tag2>mysql</tag2> <tag3>sql-server</tag3> </topusers> <topusers> <user>Nina Scholz</user> <link>http://www.stackoverflow.com//users/1447675/nina-scholz</link> <locatie>Berlijn, Duitsland</locatie> <year_rep>3.950</year_rep> <total_rep>61,135</total_rep> <tag1>javascript</tag1> <tag2>matrices</tag2> <tag3>object</tag3> </topusers> <topusers> <user>JB Nizet</user> <link>http://www.stackoverflow.com//users/571407/jb-nizet</link> <location>Saint-Etienne, Frankrijk</location> <year_rep>3.923</year_rep> <total_rep>418.780</total_rep> <tag1>java</tag1> <tag2>slaapstand</tag2> <tag3>java-8</tag3> </topusers> <topusers> <user>Frank van Puffelen</user> <link>http://www.stackoverflow.com//users/209103/frank-van-puffelen</link> <locatie>San Francisco, CA</locatie> <year_rep>3.920</year_rep> <total_rep>86,520</total_rep> <tag1>firebase</tag1> <tag2>firebase-database</tag2> <tag3>android</tag3> </topusers> <topusers> <user>dasblinkenlight</user> <link>http://www.stackoverflow.com//users/335858/dasblinkenlight</link> <location>Verenigde Staten</location> <year_rep>3.886</year_rep> <total_rep>475.813</total_rep> <tag1>c#</tag1> <tag2>java</tag2> <tag3>c++</tag3> </topusers> <topusers> <user>Tim Biegeleisen</user> <link>http://www.stackoverflow.com//users/1863229/tim-biegeleisen</link> <locatie>Singapore</locatie> <year_rep>3.814</year_rep> <total_rep>77,211</total_rep> <tag1>sql</tag1> <tag2>mysql</tag2> <tag3>java</tag3> </topusers> <topusers> <user>Greg Hewgill</user> <link>http://www.stackoverflow.com//users/893/greg-hewgill</link> <location>Christchurch, Nieuw-Zeeland</location> <year_rep>3.796</year_rep> <total_rep>529.137</total_rep> <tag1>git</tag1> <tag2>python</tag2> <tag3>git-pull</tag3> </topusers> <topusers> <user>unutbu</user> <link>http://www.stackoverflow.com//users/190597/unutbu</link> <locatie></locatie> <year_rep>3.735</year_rep> <total_rep>401.595</total_rep> <tag1>python</tag1> <tag2>panda's</tag2> <tag3>numpy</tag3> </topusers> <topusers> <user>Hans Passant</user> <link>http://www.stackoverflow.com//users/17034/hans-passant</link> <locatie>Madison, WI</locatie> <year_rep>3.688</year_rep> <total_rep>672,118</total_rep> <tag1>c#</tag1> <tag2>.net</tag2> <tag3>winforms</tag3> </topusers> <topusers> <user>Jonathan Leffler</user> <link>http://www.stackoverflow.com//users/15168/jonathan-leffler</link> <locatie>Californië, VS</locatie> <year_rep>3.649</year_rep> <total_rep>455.157</total_rep> <tag1>c</tag1> <tag2>bash</tag2> <tag3>unix</tag3> </topusers> <topusers> <user>paxdiablo</user> <link>http://www.stackoverflow.com//users/14860/paxdiablo</link> <locatie></locatie> <year_rep>3.636</year_rep> <total_rep>507.043</total_rep> <tag1>c</tag1> <tag2>c++</tag2> <tag3>bash</tag3> </topusers> <topusers> <user>Pranav C Balan</user> <link>http://www.stackoverflow.com//users/3037257/pranav-c-balan</link> <locatie>Ramanthali, Kannur, Kerala, India</locatie> <year_rep>3.604</year_rep> <total_rep>64,476</total_rep> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>html</tag3> </topusers> <topusers> <user>Suragch</user> <link>http://www.stackoverflow.com//users/3681880/suragch</link> <locatie>Hohhot, China</locatie> <year_rep>3.580</year_rep> <total_rep>71,032</total_rep> <tag1>swift</tag1> <tag2>ios</tag2> <tag3>android</tag3> </topusers> </stackoverflow> 

Python-methoden

import xml.etree.ElementTree as et import panda's als pd van io import StringIO van 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) in et.iterparse(pad): if i <= 2: first_tag = el.tag if el.tag == first_tag en len(inner) != 0: data.append(inner) inner = {} if el.text is niet Geen en 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 = {} voor 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("Invoer.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="*"/> <!-- HEADERS --> <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:anders> <xsl: text>&#xa;</xsl:text> </xsl:anders> </xsl:choose> </xsl:voor elk> <xsl:apply-templates/> </ xsl:template> <!-- DATA RIJEN (COMMA-GESCHEIDEN) --> <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:wanneer> <xsl:anders> <xsl:text>&quot;&#xa;</xsl:text> </xsl:anders> </xsl:kies> </xsl:voor-elk> </xsl:sjabloon> </xsl:transform> """ xsl = lxet.fromstring(xslstr) transform = lxet.XSLT(xsl) newdom = transform(xml) df = pd.read_csv(StringIO(str(newdom))) 

Timingen (met huidige XML en XML met 25 keer de kinderen (dwz 900 StackOverflow-gebruikersrecords)

# KORTER BESTAND python -mtimeit -s"import readxml_test_runs as test" "test.read_xml_iterfind()" 100 lussen, beste van 3: 3,87 msec per lus python -mtimeit -s"import readxml_test_runs als test" "test.read_xml_iterparse()" 100 lussen, beste van 3 : 5,5 msec per lus python -mtimeit -s"import readxml_test_runs als test" "test.read_xml_lxml_xpath()" 100 lussen, beste van 3: 3,86 msec per lus python -mtimeit -s"import readxml_test_runs als test" "test.readml_xml_lx )" 100 lussen, beste van 3: 5,68 msec per lus # GROTER BESTAND python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_iterfind()" 100 lussen, beste van 3: 36 msec per lus python -mtimeit -n"100" -s"import readxml_test_runs als test" "test.read_xml_i terparse()" 100 lussen, beste van 3: 78,9 msec per lus python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_lxml_xpath()" 100 lussen, beste van 3: 32,7 msec per lus python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_lxml_xsl()" 100 lussen, beste van 3: 51,4 msec per lus