Strategie di test del metodo Pandas read_xml()

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

Attualmente, strumenti di I/O panda non mantiene un read_xml() e la controparte to_xml(). Tuttavia, read_json dimostra che le strutture ad albero possono essere implementate per l'importazione di frame di dati e read_html per i formati di markup.

Se il team di panda considera un tale metodo read_xml per una futura versione di panda, quale implementazione farebbero perseguire: analisi con xml.etree.ElementTree integrato con le sue funzioni iterfind() o iterparse() o il modulo di terze parti, lxml con i suoi metodi XPath 1.0 e XSLT 1.0?

Di seguito sono riportati i miei test eseguiti per quattro tipi di metodo su un input XML semplice, piatto e incentrato sugli elementi. Tutti sono impostati per l'analisi generalizzata per qualsiasi figlio di secondo livello di root e ogni metodo dovrebbe produrre esattamente lo stesso dataframe panda. Tutti tranne l'ultimo chiama pd.Dataframe() nell'elenco dei dizionari. Il metodo XSLT trasforma XML in CSV per il cast di StringIO() in pd.read_csv().

Domanda (in più parti)

  • PRESTAZIONI: come spieghi l'iterparse più lento, spesso consigliato per file più grandi poiché il file viene analizzato in modo iterativo? È in parte dovuto ai controlli logici if?

  • MEMORIA: la memoria della CPU è correlata ai tempi nelle chiamate I/O? XSLT e XPath 1.0 tendono a non scalare bene con documenti XML più grandi poiché l'intero file deve essere letto in memoria per essere analizzato.

  • STRATEGIA: l'elenco dei dizionari è una strategia ottimale per Dataframe() chiamata? Vedi queste risposte interessanti: generatore versione e una versione iterwalk definita dall'utente . Entrambi gli elenchi upcast in dataframe.

Input Dati (Stack Overflow è l'attuale i migliori utenti per anno di cui sono inclusi i nostri amici panda)

<? 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, Stati Uniti</location> <year_rep>5,985</year_rep> <total_rep>499,408</total_rep> <tag1>sql</ tag1> <tag2>server-sql</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, Austria</location> <year_rep>5,835</year_rep> ; <rep_totale>154,4 39</rep_totale> <tag1>angular2</tag1> <tag2>dattiloscritto</tag2> <tag3>javascript</tag3> </topuser> <topuser> <utente>jezrael</utente> <link>http://www.stackoverflow.com//users/2901002/jezrael</link> <posizione>Bratislava, Slovacchia</posizione> <anno_rep>5,740</anno_rep> <rep_totale>83,237</rep_totale> <tag1>panda</tag1> <tag2>pitone</tag2> <tag3>frame dati</tag3> </topuser> <topuser> <utente>VonC</utente> <link>http://www.stackoverflow.com//users/6309/vonc</link> <posizione>Francia</posizione> <anno_rep>5,577</anno_rep> <rep_totale>651,397</rep_totale> <tag1>git</tag1> <tag2>github</tag2> <tag3>docker</tag3> </topuser> <topuser> <utente>Martijn Pieters</utente> <link>http://www.stackoverflow.com//users/100297/martijn-pieters</link> <posizione>Cambridge, Regno Unito</posizione> <anno_rep>5,337</anno_rep> <rep_totale>525,176</rep_totale> <tag1>pitone</tag1> <tag2>python-3.x</tag2> <tag3>python-2.7</tag3> </topuser> <topuser> <utente>TJ Crowder</utente> <link>http://www.stackoverflow.com//users/157247/tj-crowder</link> <posizione>Regno Unito</posizione> <anno_rep>5,258</anno_rep> <rep_totale>508,310</rep_totale> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>java</tag3> </topuser> <topuser> <utente>akrun</utente> <link>http://www.stackoverflow.com//users/3732271/akrun</link> <posizione></posizione> <anno_rep>5,188</anno_rep> <rep_totale>229,553</rep_totale> <tag1>r</tag1> <tag2>dplyr</tag2> <tag3>frame dati</tag3> </topuser> <topuser> <utente>Wiktor Stribi?ew</utente> <link>http://www.stackoverflow.com//users/3832970/wiktor-stribi%c5%bcew</link> <posizione>Varsavia, Polonia</posizione> <anno_rep>4,948</anno_rep> <rep_totale>158,134</rep_totale> <tag1>regex</tag1> <tag2>javascript</tag2> <tag3>c#</tag3> </topuser> <topuser> <utente>Darin Dimitrov</utente> <link>http://www.stackoverflow.com//users/29407/darin-dimitrov</link> <posizione>Sofia, Bulgaria</posizione> <anno_rep>4,936</anno_rep> <rep_totale>709,683</rep_totale> <tag1>c#</tag1> <tag2>asp.net-mvc</tag2> <tag3>asp.net-mvc-3</tag3> </topuser> <topuser> <utente>Eric Duminil</utente> <link>http://www.stackoverflow.com//users/6419007/eric-duminil</link> <posizione></posizione> <anno_rep>4,854</anno_rep> <rep_totale>12,557</rep_totale> <tag1>rubino</tag1> <tag2>ruby-on-rails</tag2> <tag3>array</tag3> </topuser> <topuser> <utente>alecxe</utente> <link>http://www.stackoverflow.com//users/771848/alecxe</link> <posizione>New York, Stati Uniti</posizione> <anno_rep>4,723</anno_rep> <rep_totale>233,368</rep_totale> <tag1>pitone</tag1> <tag2>selenio</tag2> <tag3>goniometro</tag3> </topuser> <topuser> <utente>Jean-François Fabre</utente> <link>http://www.stackoverflow.com//users/6451573/jean-fran%c3%a7ois-fabre</link> <posizione>Tolosa, Francia</posizione> <anno_rep>4,526</anno_rep> <rep_totale>30.027</rep_totale> <tag1>pitone</tag1> <tag2>python-3.x</tag2> <tag3>python-2.7</tag3> </topuser> <topuser> <utente>piRSquared</utente> <link>http://www.stackoverflow.com//users/2336654/pirsquared</link> <posizione>Bellevue, WA, Stati Uniti</posizione> <anno_rep>4,482</anno_rep> <rep_totale>41,183</rep_totale> <tag1>panda</tag1> <tag2>pitone</tag2> <tag3>frame dati</tag3> </topuser> <topuser> <utente>CommonsWare</utente> <link>http://www.stackoverflow.com//users/115145/commonsware</link> <posizione>Chi vuole sapere?</posizione> <anno_rep>4,475</anno_rep> <rep_totale>616,135</rep_totale> <tag1>Android</tag1> <tag2>java</tag2> <tag3>intento-android</tag3> </topuser> <topuser> <utente>Quentin</utente> <link>http://www.stackoverflow.com//users/19068/quentin</link> <posizione>Regno Unito</posizione> <anno_rep>4,464</anno_rep> <rep_totale>509,365</rep_totale> <tag1>javascript</tag1> <tag2>html</tag2> <tag3>css</tag3> </topuser> <topuser> <utente>Jon Skeet</utente> <link>http://www.stackoverflow.com//users/22656/jon-skeet</link> <posizione>Lettura, Regno Unito</posizione> <anno_rep>4,348</anno_rep> <rep_totale>921,690</rep_totale> <tag1>c#</tag1> <tag2>java</tag2> <tag3>.net</tag3> </topuser> <topuser> <utente>Felix Kling</utente> <link>http://www.stackoverflow.com//users/218196/felix-kling</link> <posizione>Sunnyvale, CA</posizione> <anno_rep>4,324</anno_rep> <rep_totale>411,535</rep_totale> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>asincrono</tag3> </topuser> <topuser> <utente>matt</utente> <link>http://www.stackoverflow.com//users/341994/matt</link> <posizione></posizione> <anno_rep>4,313</anno_rep> <rep_totale>220,515</rep_totale> <tag1>veloce</tag1> <tag2>ios</tag2> <tag3>xcode</tag3> </topuser> <topuser> <utente>Psidom</utente> <link>http://www.stackoverflow.com//users/4983450/psidom</link> <posizione>Atlanta, Georgia, Stati Uniti</posizione> <anno_rep>4,236</anno_rep> <rep_totale>36,950</rep_totale> <tag1>pitone</tag1> <tag2>panda</tag2> <tag3>r</tag3> </topuser> <topuser> <utente>Martin R</utente> <link>http://www.stackoverflow.com//users/1187415/martin-r</link> <posizione>Germania</posizione> <anno_rep>4,195</anno_rep> <rep_totale>269,380</rep_totale> <tag1>veloce</tag1> <tag2>ios</tag2> <tag3>swift3</tag3> </topuser> <topuser> <utente>Barmar</utente> <link>http://www.stackoverflow.com//users/1491895/barmar</link> <posizione>Arlington, MA</posizione> <anno_rep>4,179</anno_rep> <rep_totale>289,989</rep_totale> <tag1>javascript</tag1> <tag2>php</tag2> <tag3>jquery</tag3> </topuser> <topuser> <utente>Alexey Mezenin</utente> <link>http://www.stackoverflow.com//users/1227923/alexey-mezenin</link> <posizione>??????</posizione> <anno_rep>4,142</anno_rep> <rep_totale>31,602</rep_totale> <tag1>laravel</tag1> <tag2>php</tag2> <tag3>laravel-5.3</tag3> </topuser> <topuser> <utente>BalusC</utente> <link>http://www.stackoverflow.com//users/157882/balusc</link> <posizione>Amsterdam, Paesi Bassi</posizione> <anno_rep>4,046</anno_rep> <rep_totale>703,046</rep_totale> <tag1>java</tag1> <tag2>jsf</tag2> <tag3>servlet</tag3> </topuser> <topuser> <utente>GurV</utente> <link>http://www.stackoverflow.com//users/6348498/gurv</link> <posizione></posizione> <anno_rep>4,016</anno_rep> <rep_totale>7,932</rep_totale> <tag1>sql</tag1> <tag2>mysql</tag2> <tag3>server-sql</tag3> </topuser> <topuser> <utente>Nina Scholz</utente> <link>http://www.stackoverflow.com//users/1447675/nina-scholz</link> <posizione>Berlino, Germania</posizione> <anno_rep>3.950</anno_rep> <rep_totale>61,135</rep_totale> <tag1>javascript</tag1> <tag2>array</tag2> <tag3>oggetto</tag3> </topuser> <topuser> <utente>JB Nizet</utente> <link>http://www.stackoverflow.com//users/571407/jb-nizet</link> <posizione>Saint-Etienne, Francia</posizione> <anno_rep>3,923</anno_rep> <rep_totale>418,780</rep_totale> <tag1>java</tag1> <tag2>ibernazione</tag2> <tag3>java-8</tag3> </topuser> <topuser> <utente>Frank van Puffelen</utente> <link>http://www.stackoverflow.com//users/209103/frank-van-puffelen</link> <posizione>San Francisco, California</posizione> <anno_rep>3,920</anno_rep> <rep_totale>86,520</rep_totale> <tag1>firebase</tag1> <tag2>database-firebase</tag2> <tag3>Android</tag3> </topuser> <topuser> <utente>dasblinkenlight</utente> <link>http://www.stackoverflow.com//users/335858/dasblinkenlight</link> <posizione>Stati Uniti</posizione> <anno_rep>3,886</anno_rep> <rep_totale>475,813</rep_totale> <tag1>c#</tag1> <tag2>java</tag2> <tag3>c++</tag3> </topuser> <topuser> <utente>Tim Biegeleisen</utente> <link>http://www.stackoverflow.com//users/1863229/tim-biegeleisen</link> <posizione>Singapore</posizione> <anno_rep>3,814</anno_rep> <rep_totale>77,211</rep_totale> <tag1>sql</tag1> <tag2>mysql</tag2> <tag3>java</tag3> </topuser> <topuser> <utente>Greg Hewgill</utente> <link>http://www.stackoverflow.com//users/893/greg-hewgill</link> <posizione>Christchurch, Nuova Zelanda</posizione> <anno_rep>3,796</anno_rep> <rep_totale>529,137</rep_totale> <tag1>git</tag1> <tag2>pitone</tag2> <tag3>git-pull</tag3> </topuser> <topuser> <utente>unutbu</utente> <link>http://www.stackoverflow.com//users/190597/unutbu</link> <posizione></posizione> <anno_rep>3,735</anno_rep> <rep_totale>401,595</rep_totale> <tag1>pitone</tag1> <tag2>panda</tag2> <tag3>numpy</tag3> </topuser> <topuser> <utente>Hans Passant</utente> <link>http://www.stackoverflow.com//users/17034/hans-passant</link> <posizione>Madison, WI</posizione> <anno_rep>3,688</anno_rep> <rep_totale>672,118</rep_totale> <tag1>c#</tag1> <tag2>.net</tag2> <tag3>winforms</tag3> </topuser> <topuser> <utente>Jonathan Leffler</utente> <link>http://www.stackoverflow.com//users/15168/jonathan-leffler</link> <posizione>California, USA</posizione> <anno_rep>3,649</anno_rep> <rep_totale>455,157</rep_totale> <tag1>c</tag1> <tag2>bash</tag2> <tag3>unix</tag3> </topuser> <topuser> <utente>paxdiablo</utente> <link>http://www.stackoverflow.com//users/14860/paxdiablo</link> <posizione></posizione> <anno_rep>3,636</anno_rep> <rep_totale>507,043</rep_totale> <tag1>c</tag1> <tag2>c++</tag2> <tag3>bash</tag3> </topuser> <topuser> <utente>Pranav C Balan</utente> <link>http://www.stackoverflow.com//users/3037257/pranav-c-balan</link> <posizione>Ramanthali, Kannur, Kerala, India</posizione> <anno_rep>3,604</anno_rep> <rep_totale>64,476</rep_totale> <tag1>javascript</tag1> <tag2>jquery</tag2> <tag3>html</tag3> </topuser> <topuser> <utente>Suragch</utente> <link>http://www.stackoverflow.com//users/3681880/suragch</link> <posizione>Hohhot, Cina</posizione> <anno_rep>3,580</anno_rep> <rep_totale>71,032</rep_totale> <tag1>veloce</tag1> <tag2>ios</tag2> <tag3>Android</tag3> </topuser> </stackoverflow> 

Python Metodi

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) in et.iterparse(percorso): if i <= 2: first_tag = el.tag if el.tag == first_tag e len(inner) != 0: data.append(inner) inner = {} if el.text non è Nessuno e 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 = {} for 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("Input.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="*"/> <!-- INTESTAZIONI --> <xsl:template match = "/*"> <xsl:for-each select="*[1]/*"> <xsl:value-of select="local-name()" /> <xsl:choose> <xsl:quando test="posizione() != last()"> <xsl:testo>,</xsl:testo> </xsl:quando> <xsl:altrimenti> <xsl: testo>&#xa;</xsl:testo> </xsl:altrimenti> </xsl:scegli> </xsl:per-ogni> <xsl:applica-modelli/> </ xsl:template> <!-- RIGHE DI DATI (SEPARATE DA COMMA) --> <xsl:template match="/*/*" priority="2"> <xsl:for-each select=" *"> <xsl:if test="posizione() = 1"> <xsl:text>&quot;</xsl:text> </xsl:if> <xsl:value- di select="." /> <xsl:choose> <xsl:when test="position() != last()"> <xsl:text>&quot;,& quot;</xsl:testo> </xsl:quando> <xsl:altrimenti> <xsl:testo>&quot;&#xa;</xsl:testo> </xsl:altrimenti> </xsl:scegli> </xsl:per-ogni> </xsl:modello> </xsl:trasforma> """ xsl = lxet.fromstring(xslstr) transform = lxet.XSLT(xsl) newdom = transform(xml) df = pd.read_csv(StringIO(str(newdom))) 

Tempi (con XML corrente e XML con 25 volte i figli (cioè 900 record utente StackOverflow)

# SHORTER FILE python -mtimeit -s"import readxml_test_runs as test" "test.read_xml_iterfind()" 100 loop, al meglio di 3: 3,87 msec per loop python -mtimeit -s"import readxml_test_runs as test" "test.read_xml_iterparse()" 100 loop, al meglio di 3 : 5,5 msec per ciclo python -mtimeit -s"import readxml_test_runs as test" "test.read_xml_lxml_xpath()" 100 loop, al meglio di 3: 3,86 msec per ciclo python -mtimeit -s"import readxml_test_runs as test" "test.read_xml_lxml_xsl( )" 100 loop, al meglio di 3: 5,68 msec per ciclo # FILE PIÙ GRANDE python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_iterfind()" 100 loop, al meglio di 3: 36 msec per ciclo python -mtimeit -n"100" -s"import readxml_test_runs come test" "test.read_xml_i terparse()" 100 loop, al meglio di 3: 78,9 msec per ciclo python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_lxml_xpath()" 100 loop, al meglio di 3: 32,7 msec per ciclo python -mtimeit -n"100" -s"import readxml_test_runs as test" "test.read_xml_lxml_xsl()" 100 loop, al meglio di 3: 51,4 msec per loop