100% encontró este documento útil (1 voto)
632 vistas

Librería Pandas Python

Este documento describe la función read_html() en Pandas para leer tablas HTML y convertirlas en DataFrames de Pandas. Read_html() puede leer cadenas, archivos o URLs HTML y analizar las tablas, devolviendo una lista de DataFrames. También cubre opciones como especificar encabezados, índices de columnas, filas a omitir, atributos HTML, valores NaN y convertidores de columnas. El método to_html() convierte DataFrames en tablas HTML.

Cargado por

Odra Mathison
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
100% encontró este documento útil (1 voto)
632 vistas

Librería Pandas Python

Este documento describe la función read_html() en Pandas para leer tablas HTML y convertirlas en DataFrames de Pandas. Read_html() puede leer cadenas, archivos o URLs HTML y analizar las tablas, devolviendo una lista de DataFrames. También cubre opciones como especificar encabezados, índices de columnas, filas a omitir, atributos HTML, valores NaN y convertidores de columnas. El método to_html() convierte DataFrames en tablas HTML.

Cargado por

Odra Mathison
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 86

Librería Pandas Python

HTML 
Leyendo contenido HTML 
Advertencia

Nos animamos a que lea las trampas HTML tabla de análisis sintáctico por debajo con respecto a las
cuestiones relacionadas con los / html5lib / LXML analizadores BeautifulSoup4.
La read_html()función de nivel superior puede aceptar una cadena / archivo / URL HTML y
analizará las tablas HTML en la lista de pandas DataFrames. Veamos algunos ejemplos.

Nota

read_htmldevuelve un listde DataFramelos objetos, incluso si sólo hay un único cuadro que


figura en el contenido HTML.
Leer una URL sin opciones:

In [296]: url = 'https://www.fdic.gov/bank/individual/failed/banklist.html'

In [297]: dfs = pd.read_html(url)

In [298]: dfs
Out[298]:
[ Bank Name City ST CERT Acquiring
Institution Closing Date
0 The First State Bank Barboursville WV 14361
MVB Bank, Inc. April 3, 2020
1 Ericson State Bank Ericson NE 18265 Farmers and
Merchants Bank February 14, 2020
2 City National Bank of New Jersey Newark NJ 21111
Industrial Bank November 1, 2019
3 Resolute Bank Maumee OH 58317
Buckeye State Bank October 25, 2019
4 Louisa Community Bank Louisa KY 58112 Kentucky Farmers Bank
Corporation October 25, 2019
.. ... ... .. ...
... ...
556 Superior Bank, FSB Hinsdale IL 32646 Superior
Federal, FSB July 27, 2001
557 Malta National Bank Malta OH 6629 North
Valley Bank May 3, 2001
558 First Alliance Bank & Trust Co. Manchester NH 34264 Southern New Hampshire
Bank & Trust February 2, 2001
559 National State Bank of Metropolis Metropolis IL 3815 Banterra
Bank of Marion December 14, 2000
560 Bank of Honolulu Honolulu HI 21029 Bank
of the Orient October 13, 2000

[561 rows x 6 columns]]

Nota

Los datos de la URL anterior cambian todos los lunes, por lo que los datos resultantes anteriores y los
siguientes pueden ser ligeramente diferentes.
Lea el contenido del archivo de la URL anterior y páselo read_html como una cadena:

In [299]: with open(file_path, 'r') as f:


.....: dfs = pd.read_html(f.read())
.....:

In [300]: dfs
Out[300]:
[ Bank Name City ST ...
Acquiring Institution Closing Date Updated Date
0 Banks of Wisconsin d/b/a Bank of Kenosha Kenosha WI ... North
Shore Bank, FSB May 31, 2013 May 31, 2013
1 Central Arizona Bank Scottsdale AZ ...
Western State Bank May 14, 2013 May 20, 2013
2 Sunrise Bank Valdosta GA ...
Synovus Bank May 10, 2013 May 21, 2013
3 Pisgah Community Bank Asheville NC ...
Capital Bank, N.A. May 10, 2013 May 14, 2013
4 Douglas County Bank Douglasville GA ...
Hamilton State Bank April 26, 2013 May 16, 2013
.. ... ... .. ...
... ... ...
500 Superior Bank, FSB Hinsdale IL ...
Superior Federal, FSB July 27, 2001 June 5, 2012
501 Malta National Bank Malta OH ...
North Valley Bank May 3, 2001 November 18, 2002
502 First Alliance Bank & Trust Co. Manchester NH ... Southern New
Hampshire Bank & Trust February 2, 2001 February 18, 2003
503 National State Bank of Metropolis Metropolis IL ...
Banterra Bank of Marion December 14, 2000 March 17, 2005
504 Bank of Honolulu Honolulu HI ...
Bank of the Orient October 13, 2000 March 17, 2005

[505 rows x 7 columns]]

Incluso puede pasar una instancia de StringIOsi así lo desea:

In [301]: with open(file_path, 'r') as f:


.....: sio = StringIO(f.read())
.....:

In [302]: dfs = pd.read_html(sio)

In [303]: dfs
Out[303]:
[ Bank Name City ST ...
Acquiring Institution Closing Date Updated Date
0 Banks of Wisconsin d/b/a Bank of Kenosha Kenosha WI ... North
Shore Bank, FSB May 31, 2013 May 31, 2013
1 Central Arizona Bank Scottsdale AZ ...
Western State Bank May 14, 2013 May 20, 2013
2 Sunrise Bank Valdosta GA ...
Synovus Bank May 10, 2013 May 21, 2013
3 Pisgah Community Bank Asheville NC ...
Capital Bank, N.A. May 10, 2013 May 14, 2013
4 Douglas County Bank Douglasville GA ...
Hamilton State Bank April 26, 2013 May 16, 2013
.. ... ... .. ...
... ... ...
500 Superior Bank, FSB Hinsdale IL ...
Superior Federal, FSB July 27, 2001 June 5, 2012
501 Malta National Bank Malta OH ...
North Valley Bank May 3, 2001 November 18, 2002
502 First Alliance Bank & Trust Co. Manchester NH ... Southern New
Hampshire Bank & Trust February 2, 2001 February 18, 2003
503 National State Bank of Metropolis Metropolis IL ...
Banterra Bank of Marion December 14, 2000 March 17, 2005
504 Bank of Honolulu Honolulu HI ...
Bank of the Orient October 13, 2000 March 17, 2005

[505 rows x 7 columns]]


Nota

El evaluador de IPython no ejecuta los siguientes ejemplos debido al hecho de que tener tantas
funciones de acceso a la red ralentiza la compilación de la documentación. Si ve un error o un ejemplo
que no se ejecuta, no dude en informarlo en la página de problemas de pandas GitHub .
Lea una URL y haga coincidir una tabla que contenga texto específico:

match = 'Metcalf Bank'


df_list = pd.read_html(url, match=match)

Especifique una fila de encabezado (de manera predeterminada <th>o los <td>elementos ubicados


dentro de a <thead>se usan para formar el índice de columna, si hay varias filas dentro <thead>, se
crea un MultiIndex); si se especifica, la fila del encabezado se toma de los datos menos los elementos
del encabezado analizados ( <th>elementos).

dfs = pd.read_html(url, header=0)

Especifique una columna de índice:

dfs = pd.read_html(url, index_col=0)

Especifique varias filas para omitir:

dfs = pd.read_html(url, skiprows=0)

Especifique un número de filas para omitir usando una lista ( xrange(Python 2 también funciona
también):

dfs = pd.read_html(url, skiprows=range(2))

Especifique un atributo HTML:

dfs1 = pd.read_html(url, attrs={'id': 'table'})


dfs2 = pd.read_html(url, attrs={'class': 'sortable'})
print(np.array_equal(dfs1[0], dfs2[0])) # Should be True

Especifique los valores que deben convertirse a NaN:

dfs = pd.read_html(url, na_values=['No Acquirer'])

Especifique si desea mantener el conjunto predeterminado de valores NaN:


dfs = pd.read_html(url, keep_default_na=False)

Especificar convertidores para columnas. Esto es útil para datos de texto numéricos que tienen ceros a
la izquierda. Por defecto, las columnas que son numéricas se convierten en tipos numéricos y los ceros
iniciales se pierden. Para evitar esto, podemos convertir estas columnas en cadenas.

url_mcc = 'https://en.wikipedia.org/wiki/Mobile_country_code'
dfs = pd.read_html(url_mcc, match='Telekom Albania', header=0,
converters={'MNC': str})

Use alguna combinación de lo anterior:

dfs = pd.read_html(url, match='Metcalf Bank', index_col=0)

Lea en la to_htmlsalida de pandas (con alguna pérdida de precisión de coma flotante):

df = pd.DataFrame(np.random.randn(2, 2))
s = df.to_html(float_format='{0:.40g}'.format)
dfin = pd.read_html(s, index_col=0)

El lxmlbackend generará un error en un análisis fallido si ese es el único analizador que


proporciona. Si solo tiene un analizador único, puede proporcionar solo una cadena, pero se considera
una buena práctica pasar una lista con una cadena si, por ejemplo, la función espera una secuencia de
cadenas. Puedes utilizar:

dfs = pd.read_html(url, 'Metcalf Bank', index_col=0, flavor=['lxml'])

O podrías pasar flavor='lxml'sin una lista:

dfs = pd.read_html(url, 'Metcalf Bank', index_col=0, flavor='lxml')

Sin embargo, si tiene instalado bs4 y html5lib y lo aprueba Noneo lo más probable es que el análisis
tenga éxito. Tenga en cuenta que tan pronto como un análisis tenga éxito, la función volverá .
['lxml', 'bs4']

dfs = pd.read_html(url, 'Metcalf Bank', index_col=0, flavor=['lxml', 'bs4'])

Escribir en archivos HTML 


DataFrameLos objetos tienen un método de instancia to_htmlque representa el contenido
del DataFramecomo una tabla HTML. Los argumentos de la función son como en el
método to_stringdescrito anteriormente.

Nota

DataFrame.to_htmlAquí no se muestran todas las opciones posibles por razones de


brevedad. Ver to_html()para el conjunto completo de opciones.

In [304]: df = pd.DataFrame(np.random.randn(2, 2))

In [305]: df
Out[305]:
0 1
0 -0.184744 0.496971
1 -0.856240 1.857977

In [306]: print(df.to_html()) # raw html


<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>0</th>
<th>1</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>-0.184744</td>
<td>0.496971</td>
</tr>
<tr>
<th>1</th>
<td>-0.856240</td>
<td>1.857977</td>
</tr>
</tbody>
</table>

HTML:

00 1
0 - 0.49697
0 0,184744 1
1 - 1.85797
00 1
0.856240 7
El columnsargumento limitará las columnas que se muestran:

In [307]: print(df.to_html(columns=[0]))
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>0</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>-0.184744</td>
</tr>
<tr>
<th>1</th>
<td>-0.856240</td>
</tr>
</tbody>
</table>

HTML:

00
0 -
0 0,184744
-
1
0.856240
float_format toma un Python invocable para controlar la precisión de los valores de coma flotante:

In [308]: print(df.to_html(float_format='{0:.10f}'.format))
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>0</th>
<th>1</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>-0.1847438576</td>
<td>0.4969711327</td>
</tr>
<tr>
<th>1</th>
<td>-0.8562396763</td>
<td>1.8579766508</td>
</tr>
</tbody>
</table>

HTML:

00 1
0 - 0.496971132
0 0.1847438576 7
- 1.857976650
1
0.8562396763 8
bold_rows hará que las etiquetas de fila estén en negrita de forma predeterminada, pero puede
desactivarlo:

In [309]: print(df.to_html(bold_rows=False))
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>0</th>
<th>1</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>-0.184744</td>
<td>0.496971</td>
</tr>
<tr>
<td>1</td>
<td>-0.856240</td>
<td>1.857977</td>
</tr>
</tbody>
</table>
00 1
0 - 0.49697
0 0,184744 1
- 1.85797
1
0.856240 7
El classesargumento proporciona la capacidad de dar las clases CSS de la tabla HTML
resultante. Tenga en cuenta que estas clases se agregan a la 'dataframe'clase existente .

In [310]: print(df.to_html(classes=['awesome_table_class', 'even_more_awesome_class']))


<table border="1" class="dataframe awesome_table_class even_more_awesome_class">
<thead>
<tr style="text-align: right;">
<th></th>
<th>0</th>
<th>1</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>-0.184744</td>
<td>0.496971</td>
</tr>
<tr>
<th>1</th>
<td>-0.856240</td>
<td>1.857977</td>
</tr>
</tbody>
</table>

El render_linksargumento proporciona la capacidad de agregar hipervínculos a celdas que


contienen URL.

Nuevo en la versión 0.24.

In [311]: url_df = pd.DataFrame({


.....: 'name': ['Python', 'Pandas'],
.....: 'url': ['https://www.python.org/', 'https://pandas.pydata.org']})
.....:

In [312]: print(url_df.to_html(render_links=True))
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>url</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>Python</td>
<td><a href="https://www.python.org/"
target="_blank">https://www.python.org/</a></td>
</tr>
<tr>
<th>1</th>
<td>Pandas</td>
<td><a href="https://pandas.pydata.org"
target="_blank">https://pandas.pydata.org</a></td>
</tr>
</tbody>
</table>

HTML:

nombre url
0
Pitón https://www.python.org/
0
https://pandas.pydata.or
1 Pandas
g
Finalmente, el escapeargumento le permite controlar si los caracteres "<", ">" y "&" escaparon en el
HTML resultante (por defecto lo es True). Entonces, para obtener el HTML sin pasar caracteres
escapadosescape=False

In [313]: df = pd.DataFrame({'a': list('&<>'), 'b': np.random.randn(3)})

Escapado:

In [314]: print(df.to_html())
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>&amp;</td>
<td>-0.474063</td>
</tr>
<tr>
<th>1</th>
<td>&lt;</td>
<td>-0.230305</td>
</tr>
<tr>
<th>2</th>
<td>&gt;</td>
<td>-0.400654</td>
</tr>
</tbody>
</table>

una si
0 -
Y
0 0,474063
-
1 <
0,230305
-
2 >
0.400654
No escapó:

In [315]: print(df.to_html(escape=False))
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>&</td>
<td>-0.474063</td>
</tr>
<tr>
<th>1</th>
<td><</td>
<td>-0.230305</td>
</tr>
<tr>
<th>2</th>
<td>></td>
<td>-0.400654</td>
</tr>
</tbody>
</table>

una si
0 -
Y
0 0,474063
-
1 <
0,230305
-
2 >
0.400654

Nota

Es posible que algunos navegadores no muestren una diferencia en la representación de las dos tablas
HTML anteriores.

Tabla HTML que analiza Gotchas 


Hay algunos problemas de versiones que rodean a las bibliotecas que se utilizan para analizar tablas
HTML en la función pandas io de nivel superior read_html.

Problemas con lxml

 Beneficios
o lxml es muy rápido.
o lxml requiere que Cython se instale correctamente.
 Inconvenientes
o lxml qué no hace ninguna garantía sobre los resultados de su análisis sintáctico a menos
que se le da margen de beneficio estrictamente válida .
o En vista de lo anterior, hemos optado por permitirle a usted, el usuario, usar
el backend lxml , pero este backend usará html5lib si lxml no se analiza
o Por lo tanto, se recomienda encarecidamente que instale BeautifulSoup4 y html5lib ,
de modo que todavía obtenga un resultado válido (siempre que todo lo demás sea
válido) incluso si lxml falla.
Problemas con BeautifulSoup4 usando lxml como backend

 Los problemas anteriores también se mantienen aquí, ya que BeautifulSoup4 es esencialmente


un envoltorio alrededor de un backend del analizador.
Problemas con BeautifulSoup4 usando html5lib como backend

 Beneficios
o html5lib es mucho más indulgente que lxml y, en consecuencia, trata
el marcado de la vida real de una manera mucho más sensata que simplemente,
por ejemplo, soltar un elemento sin notificarte.
o html5lib genera automáticamente un marcado HTML5 válido a partir de un
marcado no válido . Esto es extremadamente importante para analizar tablas
HTML, ya que garantiza un documento válido. Sin embargo, eso NO significa
que sea "correcto", ya que el proceso de corregir el marcado no tiene una sola
definición.
o html5lib es Python puro y no requiere pasos de compilación adicionales más allá
de su propia instalación.
 Inconvenientes
o El mayor inconveniente de usar html5lib es que es lento como la melaza. Sin embargo,
considere el hecho de que muchas tablas en la web no son lo suficientemente grandes
como para que el tiempo de ejecución del algoritmo de análisis importe. Es más
probable que el cuello de botella esté en el proceso de leer el texto sin formato de la
URL en la web, es decir, IO (entrada-salida). Para tablas muy grandes, esto podría no
ser cierto.

Archivos de Excel 
El read_excel()método puede leer .xlsarchivos Excel 2003 ( ) utilizando el xlrdmódulo
Python. Los .xlsxarchivos de Excel 2007+ ( ) se pueden leer
usando xlrdo openpyxl. Los .xlsbarchivos binarios de Excel ( ) se pueden leer
usando pyxlsb. El to_excel()método de instancia se usa para guardar un DataFramearchivo en
Excel. En general, la semántica es similar a trabajar con datos csv . Vea el libro de cocina para algunas
estrategias avanzadas.

Leyendo archivos de Excel 


En el caso de uso más básico, read_exceltoma una ruta a un archivo de Excel y
le sheet_nameindica qué hoja analizar.

# Returns a DataFrame
pd.read_excel('path_to_file.xls', sheet_name='Sheet1')

ExcelFileclase 
Para facilitar el trabajo con varias hojas del mismo archivo, la ExcelFile clase se puede usar para
envolver el archivo y se puede pasar a. read_excel Habrá un beneficio de rendimiento para leer
varias hojas ya que el archivo se lee en la memoria solo una vez.

xlsx = pd.ExcelFile('path_to_file.xls')
df = pd.read_excel(xlsx, 'Sheet1')

La ExcelFileclase también se puede usar como administrador de contexto.

with pd.ExcelFile('path_to_file.xls') as xls:


df1 = pd.read_excel(xls, 'Sheet1')
df2 = pd.read_excel(xls, 'Sheet2')

La sheet_namespropiedad generará una lista de los nombres de las hojas en el archivo.

El caso de uso principal para un ExcelFilees analizar varias hojas con diferentes parámetros:

data = {}
# For when Sheet1's format differs from Sheet2
with pd.ExcelFile('path_to_file.xls') as xls:
data['Sheet1'] = pd.read_excel(xls, 'Sheet1', index_col=None,
na_values=['NA'])
data['Sheet2'] = pd.read_excel(xls, 'Sheet2', index_col=1)

Tenga en cuenta que si se utilizan los mismos parámetros de análisis para todas las hojas, simplemente
se puede pasar una lista de nombres de hoja read_excelsin pérdida de rendimiento.

# using the ExcelFile class


data = {}
with pd.ExcelFile('path_to_file.xls') as xls:
data['Sheet1'] = pd.read_excel(xls, 'Sheet1', index_col=None,
na_values=['NA'])
data['Sheet2'] = pd.read_excel(xls, 'Sheet2', index_col=None,
na_values=['NA'])

# equivalent using the read_excel function


data = pd.read_excel('path_to_file.xls', ['Sheet1', 'Sheet2'],
index_col=None, na_values=['NA'])

ExcelFileTambién se puede llamar con un xlrd.book.Bookobjeto como parámetro. Esto permite


al usuario controlar cómo se lee el archivo de Excel. Por ejemplo, las hojas se pueden cargar a pedido
llamando xlrd.open_workbook() al on_demand=True.
import xlrd
xlrd_book = xlrd.open_workbook('path_to_file.xls', on_demand=True)
with pd.ExcelFile(xlrd_book) as xls:
df1 = pd.read_excel(xls, 'Sheet1')
df2 = pd.read_excel(xls, 'Sheet2')

Especificando hojas 
Nota

El segundo argumento es sheet_name, no debe confundirse con ExcelFile.sheet_names.

Nota

El atributo de un ExcelFile sheet_namesproporciona acceso a una lista de hojas.


 Los argumentos sheet_namepermiten especificar la hoja o hojas para leer.
 El valor predeterminado para sheet_name0 es, lo que indica que debe leer la primera hoja.
 Pase una cadena para referirse al nombre de una hoja en particular en el libro.
 Pase un número entero para referirse al índice de una hoja. Los índices siguen la convención de
Python, comenzando en 0.
 Pase una lista de cadenas o enteros para devolver un diccionario de hojas especificadas.
 Pase a Nonepara devolver un diccionario de todas las hojas disponibles.
# Returns a DataFrame
pd.read_excel('path_to_file.xls', 'Sheet1', index_col=None, na_values=['NA'])

Usando el índice de la hoja:

# Returns a DataFrame
pd.read_excel('path_to_file.xls', 0, index_col=None, na_values=['NA'])

Usando todos los valores predeterminados:

# Returns a DataFrame
pd.read_excel('path_to_file.xls')

Usando None para obtener todas las hojas:

# Returns a dictionary of DataFrames


pd.read_excel('path_to_file.xls', sheet_name=None)

Usando una lista para obtener múltiples hojas:


# Returns the 1st and 4th sheet, as a dictionary of DataFrames.
pd.read_excel('path_to_file.xls', sheet_name=['Sheet1', 3])

read_excelpuede leer más de una hoja, configurando sheet_nameuna lista de nombres de hojas,


una lista de posiciones de hojas o Noneleyendo todas las hojas. Las hojas se pueden especificar por
índice de hoja o nombre de hoja, usando un entero o una cadena, respectivamente.

Leyendo un MultiIndex
read_excelpuede leer un MultiIndexíndice, pasando una lista de columnas a index_col y
una MultiIndexcolumna pasando una lista de filas a header. Si los nombres de los niveles son
serializados index o columnsse leerán también especificando las filas / columnas que componen los
niveles.

Por ejemplo, para leer en un MultiIndexíndice sin nombres:

In [316]: df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [5, 6, 7, 8]},


.....: index=pd.MultiIndex.from_product([['a', 'b'], ['c', 'd']]))
.....:

In [317]: df.to_excel('path_to_file.xlsx')

In [318]: df = pd.read_excel('path_to_file.xlsx', index_col=[0, 1])

In [319]: df
Out[319]:
a b
a c 1 5
d 2 6
b c 3 7
d 4 8

Si el índice tiene nombres de nivel, también se analizarán, utilizando los mismos parámetros.

In [320]: df.index = df.index.set_names(['lvl1', 'lvl2'])

In [321]: df.to_excel('path_to_file.xlsx')

In [322]: df = pd.read_excel('path_to_file.xlsx', index_col=[0, 1])

In [323]: df
Out[323]:
a b
lvl1 lvl2
a c 1 5
d 2 6
b c 3 7
d 4 8

Si el archivo fuente tiene MultiIndexíndices y columnas, las listas que especifican cada una deben
pasarse a index_coly header:

In [324]: df.columns = pd.MultiIndex.from_product([['a'], ['b', 'd']],


.....: names=['c1', 'c2'])
.....:

In [325]: df.to_excel('path_to_file.xlsx')

In [326]: df = pd.read_excel('path_to_file.xlsx', index_col=[0, 1], header=[0, 1])

In [327]: df
Out[327]:
c1 a
c2 b d
lvl1 lvl2
a c 1 5
d 2 6
b c 3 7
d 4 8

Analizando columnas específicas 


A menudo, los usuarios insertarán columnas para realizar cálculos temporales en Excel y es posible que
no desee leer en esas columnas. read_exceltoma una usecolspalabra clave para permitirle
especificar un subconjunto de columnas para analizar.

En desuso desde la versión 0.24.0.

Pasar un entero para usecolsha quedado en desuso. Pase una lista de entradas de 0


a usecolsinclusivo en su lugar.

Si usecolses un número entero, se supone que indica la última columna a analizar.

pd.read_excel('path_to_file.xls', 'Sheet1', usecols=2)

También puede especificar un conjunto delimitado por comas de columnas y rangos de Excel como una
cadena:
pd.read_excel('path_to_file.xls', 'Sheet1', usecols='A,C:E')

Si se usecolstrata de una lista de enteros, se supone que son los índices de las columnas del archivo a
analizar.

pd.read_excel('path_to_file.xls', 'Sheet1', usecols=[0, 2, 3])

El orden de los elementos se ignora, por lo que es lo mismo que .usecols=[0, 1][1, 0]

Nuevo en la versión 0.24.

Si se usecolstrata de una lista de cadenas, se supone que cada cadena corresponde a un nombre de
columna proporcionado por el usuario nameso inferido de la (s) fila (s) del encabezado del
documento. Esas cadenas definen qué columnas se analizarán:

pd.read_excel('path_to_file.xls', 'Sheet1', usecols=['foo', 'bar'])

El orden de los elementos se ignora, por lo que es lo mismo que .usecols=['baz', 'joe']


['joe', 'baz']

Nuevo en la versión 0.24.

Si usecolses invocable, la función invocable se evaluará con los nombres de columna, devolviendo
nombres donde se evalúa la función invocable True.

pd.read_excel('path_to_file.xls', 'Sheet1', usecols=lambda x: x.isalpha())

Analizando fechas 
Los valores de fecha y hora normalmente se convierten automáticamente al tipo apropiado cuando se
lee el archivo de Excel. Pero si tiene una columna de cadenas que parecen fechas (pero en realidad no
están formateadas como fechas en Excel), puede usar la parse_datespalabra clave para analizar esas
cadenas en fechas y horas:

pd.read_excel('path_to_file.xls', 'Sheet1', parse_dates=['date_strings'])

Convertidores de celdas 
Es posible transformar el contenido de las celdas de Excel mediante la converters opción Por
ejemplo, para convertir una columna a booleana:
pd.read_excel('path_to_file.xls', 'Sheet1', converters={'MyBools': bool})

Esta opción maneja los valores faltantes y trata las excepciones en los convertidores como datos
faltantes. Las transformaciones se aplican celda por celda en lugar de a la columna como un todo, por
lo que no se garantiza el tipo de matriz. Por ejemplo, una columna de enteros con valores faltantes no
se puede transformar en una matriz con dtype entero, porque NaN es estrictamente flotante. Puede
enmascarar manualmente los datos faltantes para recuperar el tipo de entero:

def cfun(x):
return int(x) if x else -1

pd.read_excel('path_to_file.xls', 'Sheet1', converters={'MyInts': cfun})

Especificaciones de tipo 
Como alternativa a los convertidores, el tipo para una columna completa se puede especificar usando
la palabra clave dtype , que lleva los nombres de columnas de un mapeo de diccionario a tipos. Para
interpretar datos sin inferencia de tipos, use el tipo stro object.

pd.read_excel('path_to_file.xls', dtype={'MyInts': 'int64', 'MyText': str})

Escribir archivos de Excel 


Escribir archivos de Excel en el disco 
Para escribir un DataFrameobjeto en una hoja de un archivo de Excel, puede usar
el to_excelmétodo de instancia. Los argumentos son en gran medida los mismos que
se to_csv describieron anteriormente, el primer argumento es el nombre del archivo de Excel y el
segundo argumento opcional el nombre de la hoja en la que se DataFramedebe escribir. Por ejemplo:

df.to_excel('path_to_file.xlsx', sheet_name='Sheet1')

Los archivos con una .xlsextensión se escribirán usando xlwty aquellos con una .xlsxextensión se


escribirán usando xlsxwriter(si está disponible) o openpyxl.

Se DataFrameescribirá de una manera que intente imitar la salida REPL. El index_labelse colocará


en la segunda fila en lugar de la primera. Se puede colocar en la primera fila estableciendo
la merge_cellsopción to_excel()de False:

df.to_excel('path_to_file.xlsx', index_label='label', merge_cells=False)


Para escribir DataFrameshojas separadas en hojas separadas en un solo archivo de Excel, uno puede
pasar un ExcelWriter.

with pd.ExcelWriter('path_to_file.xlsx') as writer:


df1.to_excel(writer, sheet_name='Sheet1')
df2.to_excel(writer, sheet_name='Sheet2')

Nota

Exprimiendo un poco más de rendimiento read_excel internamente, Excel almacena todos los datos


numéricos como flotantes. Debido a que esto puede producir un comportamiento inesperado al leer
datos, los pandas de manera predeterminada intentan convertir enteros en flotantes si no pierde
información ( ). Puede pasar para deshabilitar este comportamiento, lo que puede mejorar ligeramente
el rendimiento.1.0 --> 1convert_float=False

Escribir archivos de Excel en la memoria 


Pandas admite la escritura de archivos de Excel en objetos similares al búfer,
como StringIOo BytesIOusando ExcelWriter.

# Safe import for either Python 2.x or 3.x


try:
from io import BytesIO
except ImportError:
from cStringIO import StringIO as BytesIO

bio = BytesIO()

# By setting the 'engine' in the ExcelWriter constructor.


writer = pd.ExcelWriter(bio, engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1')

# Save the workbook


writer.save()

# Seek to the beginning and read to copy the workbook to a variable in memory
bio.seek(0)
workbook = bio.read()

Nota

engineEs opcional pero recomendado. La configuración del motor determina la versión del libro de
trabajo producido. La configuración engine='xlrd'producirá un libro de trabajo en formato Excel
2003 (xls). Si usa 'openpyxl'o 'xlsxwriter'producirá un libro de trabajo en formato Excel 2007
(xlsx). Si se omite, se genera un libro de trabajo con formato Excel 2007.

Motores de escritor de Excel 


Pandas elige un escritor Excel a través de dos métodos:

1. el engineargumento de la palabra clave


2. la extensión del nombre de archivo (a través del valor predeterminado especificado en las
opciones de configuración)
De forma predeterminada, pandas usa XlsxWriter para .xlsx, openpyxl para .xlsmy xlwt para
los .xlsarchivos. Si tiene varios motores instalados, puede configurar el motor
predeterminado configurando las opciones de
configuración io.excel.xlsx.writer y io.excel.xls.writer. los pandas recurrirán
a openpyxl para .xlsx archivos si Xlsxwriter no está disponible.

Para especificar qué escritor desea usar, puede pasar un argumento de palabra clave del motor
a to_excely para ExcelWriter. Los motores incorporados son:

 openpyxl: se requiere la versión 2.4 o superior


 xlsxwriter
 xlwt
# By setting the 'engine' in the DataFrame 'to_excel()' methods.
df.to_excel('path_to_file.xlsx', sheet_name='Sheet1', engine='xlsxwriter')

# By setting the 'engine' in the ExcelWriter constructor.


writer = pd.ExcelWriter('path_to_file.xlsx', engine='xlsxwriter')

# Or via pandas configuration.


from pandas import options # noqa: E402
options.io.excel.xlsx.writer = 'xlsxwriter'

df.to_excel('path_to_file.xlsx', sheet_name='Sheet1')

Estilo y formato 
El aspecto de las hojas de cálculo de Excel creado a partir de los pandas se pueden modificar mediante
los siguientes parámetros en el DataFrame's to_excelmétodo.

 float_format: Cadena de formato para números de coma flotante (predeterminado None).


 freeze_panes: Una tupla de dos enteros que representan la fila más inferior y la columna más
a la derecha para congelar. Cada uno de estos parámetros está basado en uno, por lo que (1, 1)
congelará la primera fila y la primera columna (predeterminado None).
El uso del motor Xlsxwriter proporciona muchas opciones para controlar el formato de una hoja de
cálculo de Excel creada con el to_excelmétodo. Se pueden encontrar excelentes ejemplos en
la documentación de Xlsxwriter aquí: https://xlsxwriter.readthedocs.io/working_with_pandas.html

Hojas de cálculo de OpenDocument 


Nuevo en la versión 0.25.

El read_excel()método también puede leer hojas de cálculo de OpenDocument utilizando


el odfpymódulo. La semántica y características para la lectura de las hojas de cálculo de
OpenDocument coinciden con qué se puede hacer para archivos de Excel usando engine='odf'.

# Returns a DataFrame
pd.read_excel('path_to_file.ods', engine='odf')

Nota

Actualmente, pandas solo admite la lectura de hojas de cálculo de OpenDocument. La escritura no está
implementada.

Archivos binarios de Excel (.xlsb) 


Nuevo en la versión 1.0.0.

El read_excel()método también puede leer archivos binarios de Excel utilizando


el pyxlsbmódulo. La semántica y las características para leer archivos binarios de Excel coinciden
principalmente con lo que se puede hacer para usar archivos de Excelengine='pyxlsb' . pyxlsbno
reconoce los tipos de fecha y hora en los archivos y en su lugar devolverá flotantes.

# Returns a DataFrame
pd.read_excel('path_to_file.xlsb', engine='pyxlsb')

Nota

Actualmente, pandas solo admite la lectura de archivos binarios de Excel. La escritura no está
implementada.

Portapapeles 
Una forma práctica de obtener datos es usar el read_clipboard()método, que toma el contenido del
búfer del portapapeles y los pasa al read_csvmétodo. Por ejemplo, puede copiar el siguiente texto en
el portapapeles (CTRL-C en muchos sistemas operativos):
A B C
x 1 4 p
y 2 5 q
z 3 6 r

Y luego importe los datos directamente a a DataFramellamando a:

>>> clipdf = pd.read_clipboard()


>>> clipdf
A B C
x 1 4 p
y 2 5 q
z 3 6 r

El to_clipboardmétodo se puede utilizar para escribir el contenido de DataFramea en el


portapapeles. A continuación, puede pegar el contenido del portapapeles en otras aplicaciones (CTRL-
V en muchos sistemas operativos). Aquí ilustramos cómo escribir un DataFrameportapapeles y volver
a leerlo.

>>> df = pd.DataFrame({'A': [1, 2, 3],


... 'B': [4, 5, 6],
... 'C': ['p', 'q', 'r']},
... index=['x', 'y', 'z'])
>>> df
A B C
x 1 4 p
y 2 5 q
z 3 6 r
>>> df.to_clipboard()
>>> pd.read_clipboard()
A B C
x 1 4 p
y 2 5 q
z 3 6 r

Podemos ver que recuperamos el mismo contenido, que habíamos escrito anteriormente en el
portapapeles.

Nota

Es posible que necesite instalar xclip o xsel (con PyQt5, PyQt4 o qtpy) en Linux para usar estos
métodos.
Decapado 
Todos los objetos pandas están equipados con to_picklemétodos que utilizan el cPicklemódulo de
Python para guardar estructuras de datos en el disco utilizando el formato pickle.

In [328]: df
Out[328]:
c1 a
c2 b d
lvl1 lvl2
a c 1 5
d 2 6
b c 3 7
d 4 8

In [329]: df.to_pickle('foo.pkl')

La read_picklefunción en el pandasespacio de nombres se puede usar para cargar cualquier objeto


pandas en escabeche (o cualquier otro objeto en escabeche) desde el archivo:

In [330]: pd.read_pickle('foo.pkl')
Out[330]:
c1 a
c2 b d
lvl1 lvl2
a c 1 5
d 2 6
b c 3 7
d 4 8

Advertencia

La carga de datos encurtidos recibidos de fuentes no confiables puede ser insegura.

Ver: https://docs.python.org/3/library/pickle.html

Advertencia

read_pickle() solo está garantizado compatible con versiones anteriores de pandas versión 0.20.3

Archivos encurtidos comprimidos 


read_pickle(), DataFrame.to_pickle()y Series.to_pickle()puede leer y escribir archivos
encurtidos comprimidos. Los tipos de compresión de gzip, bz2, xzson compatibles con la lectura y
la escritura. El zipformato de archivo solo admite lectura y debe contener solo un archivo de datos
para leer.

El tipo de compresión puede ser un parámetro explícito o inferirse de la extensión del archivo. Si
'infer', a continuación, utilizar gzip, bz2, zip, o xzsi extremos nombre de archivo
en '.gz', '.bz2', '.zip', o '.xz', respectivamente.

In [331]: df = pd.DataFrame({
.....: 'A': np.random.randn(1000),
.....: 'B': 'foo',
.....: 'C': pd.date_range('20130101', periods=1000, freq='s')})
.....:

In [332]: df
Out[332]:
A B C
0 -0.288267 foo 2013-01-01 00:00:00
1 -0.084905 foo 2013-01-01 00:00:01
2 0.004772 foo 2013-01-01 00:00:02
3 1.382989 foo 2013-01-01 00:00:03
4 0.343635 foo 2013-01-01 00:00:04
.. ... ... ...
995 -0.220893 foo 2013-01-01 00:16:35
996 0.492996 foo 2013-01-01 00:16:36
997 -0.461625 foo 2013-01-01 00:16:37
998 1.361779 foo 2013-01-01 00:16:38
999 -1.197988 foo 2013-01-01 00:16:39

[1000 rows x 3 columns]

Usando un tipo de compresión explícito:

In [333]: df.to_pickle("data.pkl.compress", compression="gzip")

In [334]: rt = pd.read_pickle("data.pkl.compress", compression="gzip")

In [335]: rt
Out[335]:
A B C
0 -0.288267 foo 2013-01-01 00:00:00
1 -0.084905 foo 2013-01-01 00:00:01
2 0.004772 foo 2013-01-01 00:00:02
3 1.382989 foo 2013-01-01 00:00:03
4 0.343635 foo 2013-01-01 00:00:04
.. ... ... ...
995 -0.220893 foo 2013-01-01 00:16:35
996 0.492996 foo 2013-01-01 00:16:36
997 -0.461625 foo 2013-01-01 00:16:37
998 1.361779 foo 2013-01-01 00:16:38
999 -1.197988 foo 2013-01-01 00:16:39

[1000 rows x 3 columns]

Inferir el tipo de compresión de la extensión:

In [336]: df.to_pickle("data.pkl.xz", compression="infer")

In [337]: rt = pd.read_pickle("data.pkl.xz", compression="infer")

In [338]: rt
Out[338]:
A B C
0 -0.288267 foo 2013-01-01 00:00:00
1 -0.084905 foo 2013-01-01 00:00:01
2 0.004772 foo 2013-01-01 00:00:02
3 1.382989 foo 2013-01-01 00:00:03
4 0.343635 foo 2013-01-01 00:00:04
.. ... ... ...
995 -0.220893 foo 2013-01-01 00:16:35
996 0.492996 foo 2013-01-01 00:16:36
997 -0.461625 foo 2013-01-01 00:16:37
998 1.361779 foo 2013-01-01 00:16:38
999 -1.197988 foo 2013-01-01 00:16:39

[1000 rows x 3 columns]

El valor predeterminado es 'inferir':

In [339]: df.to_pickle("data.pkl.gz")

In [340]: rt = pd.read_pickle("data.pkl.gz")

In [341]: rt
Out[341]:
A B C
0 -0.288267 foo 2013-01-01 00:00:00
1 -0.084905 foo 2013-01-01 00:00:01
2 0.004772 foo 2013-01-01 00:00:02
3 1.382989 foo 2013-01-01 00:00:03
4 0.343635 foo 2013-01-01 00:00:04
.. ... ... ...
995 -0.220893 foo 2013-01-01 00:16:35
996 0.492996 foo 2013-01-01 00:16:36
997 -0.461625 foo 2013-01-01 00:16:37
998 1.361779 foo 2013-01-01 00:16:38
999 -1.197988 foo 2013-01-01 00:16:39

[1000 rows x 3 columns]

In [342]: df["A"].to_pickle("s1.pkl.bz2")

In [343]: rt = pd.read_pickle("s1.pkl.bz2")

In [344]: rt
Out[344]:
0 -0.288267
1 -0.084905
2 0.004772
3 1.382989
4 0.343635
...
995 -0.220893
996 0.492996
997 -0.461625
998 1.361779
999 -1.197988
Name: A, Length: 1000, dtype: float64

msgpack 
El soporte para pandas msgpackse ha eliminado en la versión 1.0.0. Se recomienda utilizar pyarrow
para la transmisión en línea de objetos de pandas.

Ejemplo de uso de pyarrow:

>>> import pandas as pd


>>> import pyarrow as pa
>>> df = pd.DataFrame({'A': [1, 2, 3]})
>>> context = pa.default_serialization_context()
>>> df_bytestring = context.serialize(df).to_buffer().to_pybytes()

Para obtener documentación sobre pyarrow, consulte aquí .


HDF5 (PyTables) 
HDFStorees un objeto tipo dict que lee y escribe pandas utilizando el formato HDF5 de alto
rendimiento utilizando la excelente biblioteca PyTables . Vea el libro de cocina para algunas
estrategias avanzadas.

Advertencia

pandas requiere PyTables> = 3.0.0. Hay un error de indexación en PyTables<3.2 que puede


aparecer al consultar tiendas usando un índice. Si ve que se devuelve un subconjunto de
resultados, actualice a PyTables> = 3.2. Las tiendas creadas previamente deberán reescribirse
utilizando la versión actualizada.

In [345]: store = pd.HDFStore('store.h5')

In [346]: print(store)
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

Los objetos se pueden escribir en el archivo al igual que agregar pares clave-valor a un dict:

In [347]: index = pd.date_range('1/1/2000', periods=8)

In [348]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [349]: df = pd.DataFrame(np.random.randn(8, 3), index=index,


.....: columns=['A', 'B', 'C'])
.....:

# store.put('s', s) is an equivalent method


In [350]: store['s'] = s

In [351]: store['df'] = df

In [352]: store
Out[352]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

En una sesión actual o posterior de Python, puede recuperar objetos almacenados:

# store.get('df') is an equivalent method


In [353]: store['df']
Out[353]:
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288

# dotted (attribute) access provides get as well


In [354]: store.df
Out[354]:
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288

Eliminación del objeto especificado por la clave:

# store.remove('df') is an equivalent method


In [355]: del store['df']

In [356]: store
Out[356]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

Cerrar una tienda y usar un administrador de contexto:

In [357]: store.close()

In [358]: store
Out[358]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

In [359]: store.is_open
Out[359]: False
# Working with, and automatically closing the store using a context manager
In [360]: with pd.HDFStore('store.h5') as store:
.....: store.keys()
.....:

API de lectura / escritura 


HDFStoreadmite una API de nivel superior que utiliza read_hdfpara leer y to_hdfescribir, similar a
cómo read_csvy cómo to_csvfunciona.

In [361]: df_tl = pd.DataFrame({'A': list(range(5)), 'B': list(range(5))})

In [362]: df_tl.to_hdf('store_tl.h5', 'table', append=True)

In [363]: pd.read_hdf('store_tl.h5', 'table', where=['index>2'])


Out[363]:
A B
3 3 3
4 4 4

HDFStore por defecto no soltará las filas que faltan. Este comportamiento se puede cambiar
mediante la configuración dropna=True.

In [364]: df_with_missing = pd.DataFrame({'col1': [0, np.nan, 2],


.....: 'col2': [1, np.nan, np.nan]})
.....:

In [365]: df_with_missing
Out[365]:
col1 col2
0 0.0 1.0
1 NaN NaN
2 2.0 NaN

In [366]: df_with_missing.to_hdf('file.h5', 'df_with_missing',


.....: format='table', mode='w')
.....:

In [367]: pd.read_hdf('file.h5', 'df_with_missing')


Out[367]:
col1 col2
0 0.0 1.0
1 NaN NaN
2 2.0 NaN

In [368]: df_with_missing.to_hdf('file.h5', 'df_with_missing',


.....: format='table', mode='w', dropna=True)
.....:

In [369]: pd.read_hdf('file.h5', 'df_with_missing')


Out[369]:
col1 col2
0 0.0 1.0
1 NaN NaN
2 2.0 NaN

Formato fijo 
Los ejemplos anteriores muestran el uso de almacenamiento put, que escribe el HDF5 PyTablesen
un formato de matriz fijo, denominado fixedformato. Estos tipos de tiendas no se pueden agregar
una vez escritos (aunque simplemente puede eliminarlos y volver a escribir). Tampoco
son cuestionables ; deben ser recuperados en su totalidad. Tampoco admiten marcos de datos con
nombres de columna no únicos. Las fixedtiendas de formatos ofrecen una escritura muy rápida y
una lectura ligeramente más rápida que las tabletiendas. Este formato se especifica por defecto
cuando se usa puto to_hdfo por format='fixed'o format='f'.

Advertencia

Aparecerá un fixedformato TypeErrorsi intenta recuperar utilizando un where:

>>> pd.DataFrame(np.random.randn(10, 2)).to_hdf('test_fixed.h5', 'df')


>>> pd.read_hdf('test_fixed.h5', 'df', where='index>5')
TypeError: cannot pass a where specification when reading a fixed format.
this store must be selected in its entirety

Formato de tabla 
HDFStoreadmite otro PyTablesformato en disco, el table formato. Conceptualmente,
a tabletiene una forma muy similar a un DataFrame, con filas y columnas. A tablepuede agregarse
en la misma u otras sesiones. Además, se admiten operaciones de tipo de consulta y
eliminación. Este formato se especifica
mediante format='table'o format='t' hacia appendo puto to_hdf.

Este formato también se puede configurar como una


opción pd.set_option('io.hdf.default_format','table') para habilitar
el put/append/to_hdfalmacenamiento predeterminado en el tableformato.
In [370]: store = pd.HDFStore('store.h5')

In [371]: df1 = df[0:4]

In [372]: df2 = df[4:]

# append data (creates a table automatically)


In [373]: store.append('df', df1)

In [374]: store.append('df', df2)

In [375]: store
Out[375]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

# select the entire object


In [376]: store.select('df')
Out[376]:
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288

# the type of stored data


In [377]: store.root.df._v_attrs.pandas_type
Out[377]: 'frame_table'

Nota

También puede crear un tablepase format='table'o format='t'una putoperación.

Claves jerárquicas 
Las claves de una tienda se pueden especificar como una cadena. Estos pueden estar en un
formato de nombre de ruta jerárquico (por ejemplo foo/bar/bah), que generará una jerarquía de
sub-tiendas (o Groupsen lenguaje PyTables). Las claves se pueden especificar sin la '/' inicial
y siempre son absolutas (por ejemplo, 'foo' se refiere a '/ foo'). Las operaciones de eliminación
pueden eliminar todo en la sub-tienda y debajo , así que tenga cuidado .
In [378]: store.put('foo/bar/bah', df)

In [379]: store.append('food/orange', df)

In [380]: store.append('food/apple', df)

In [381]: store
Out[381]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

# a list of keys are returned


In [382]: store.keys()
Out[382]: ['/df', '/food/apple', '/food/orange', '/foo/bar/bah']

# remove all nodes under this level


In [383]: store.remove('food')

In [384]: store
Out[384]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

Puede recorrer la jerarquía de grupos utilizando el walkmétodo que generará una tupla para cada
clave de grupo junto con las claves relativas de su contenido.

Nuevo en la versión 0.24.0.

In [385]: for (path, subgroups, subkeys) in store.walk():


.....: for subgroup in subgroups:
.....: print('GROUP: {}/{}'.format(path, subgroup))
.....: for subkey in subkeys:
.....: key = '/'.join([path, subkey])
.....: print('KEY: {}'.format(key))
.....: print(store.get(key))
.....:
GROUP: /foo
KEY: /df
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288
GROUP: /foo/bar
KEY: /foo/bar/bah
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288

Advertencia

Las claves jerárquicas no se pueden recuperar como acceso punteado (atributo) como se describió
anteriormente para los elementos almacenados en el nodo raíz.

In [8]: store.foo.bar.bah
AttributeError: 'HDFStore' object has no attribute 'foo'

# you can directly access the actual PyTables node but using the root node
In [9]: store.root.foo.bar.bah
Out[9]:
/foo/bar/bah (Group) ''
children := ['block0_items' (Array), 'block0_values' (Array), 'axis0' (Array), 'axis1'
(Array)]

En su lugar, use claves explícitas basadas en cadenas:

In [386]: store['foo/bar/bah']
Out[386]:
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288
Almacenando tipos 
Almacenar tipos mixtos en una tabla 
Se admite el almacenamiento de datos de tipo mixto. Las cadenas se almacenan como un ancho
fijo utilizando el tamaño máximo de la columna adjunta. Los intentos posteriores de agregar
cadenas más largas generarán a ValueError.

Pasar como un parámetro para agregar establecerá un mínimo mayor para las columnas de
cadena. El almacenamiento es actualmente compatible. Para las columnas de cadena, pasar anexar
cambiará la representación predeterminada de nan en el disco (que se convierte a / desde np.nan ),
esto por defecto
es nan .min_itemsize={`values`: size}floats, strings, ints, bools, datetime64nan_rep = 'nan
'

In [387]: df_mixed = pd.DataFrame({'A': np.random.randn(8),


.....: 'B': np.random.randn(8),
.....: 'C': np.array(np.random.randn(8), dtype='float32'),
.....: 'string': 'string',
.....: 'int': 1,
.....: 'bool': True,
.....: 'datetime64': pd.Timestamp('20010102')},
.....: index=list(range(8)))
.....:

In [388]: df_mixed.loc[df_mixed.index[3:5],
.....: ['A', 'B', 'string', 'datetime64']] = np.nan
.....:

In [389]: store.append('df_mixed', df_mixed, min_itemsize={'values': 50})

In [390]: df_mixed1 = store.select('df_mixed')

In [391]: df_mixed1
Out[391]:
A B C string int bool datetime64
0 -0.116008 0.743946 -0.398501 string 1 True 2001-01-02
1 0.592375 -0.533097 -0.677311 string 1 True 2001-01-02
2 0.476481 -0.140850 -0.874991 string 1 True 2001-01-02
3 NaN NaN -1.167564 NaN 1 True NaT
4 NaN NaN -0.593353 NaN 1 True NaT
5 0.852727 0.463819 0.146262 string 1 True 2001-01-02
6 -1.177365 0.793644 -0.131959 string 1 True 2001-01-02
7 1.236988 0.221252 0.089012 string 1 True 2001-01-02
In [392]: df_mixed1.dtypes.value_counts()
Out[392]:
float64 2
float32 1
datetime64[ns] 1
bool 1
object 1
int64 1
dtype: int64

# we have provided a minimum string column size


In [393]: store.root.df_mixed.table
Out[393]:
/df_mixed/table (Table(8,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": Float64Col(shape=(2,), dflt=0.0, pos=1),
"values_block_1": Float32Col(shape=(1,), dflt=0.0, pos=2),
"values_block_2": Int64Col(shape=(1,), dflt=0, pos=3),
"values_block_3": Int64Col(shape=(1,), dflt=0, pos=4),
"values_block_4": BoolCol(shape=(1,), dflt=False, pos=5),
"values_block_5": StringCol(itemsize=50, shape=(1,), dflt=b'', pos=6)}
byteorder := 'little'
chunkshape := (689,)
autoindex := True
colindexes := {
"index": Index(6, medium, shuffle, zlib(1)).is_csi=False}

Almacenamiento de marcos de datos de índice múltiple 


Almacenar MultiIndex DataFramescomo tablas es muy similar a almacenar / seleccionar desde un
índice homogéneo DataFrames.

In [394]: index = pd.MultiIndex(levels=[['foo', 'bar', 'baz', 'qux'],


.....: ['one', 'two', 'three']],
.....: codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3],
.....: [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]],
.....: names=['foo', 'bar'])
.....:

In [395]: df_mi = pd.DataFrame(np.random.randn(10, 3), index=index,


.....: columns=['A', 'B', 'C'])
.....:
In [396]: df_mi
Out[396]:
A B C
foo bar
foo one 0.667450 0.169405 -1.358046
two -0.105563 0.492195 0.076693
three 0.213685 -0.285283 -1.210529
bar one -1.408386 0.941577 -0.342447
two 0.222031 0.052607 2.093214
baz two 1.064908 1.778161 -0.913867
three -0.030004 -0.399846 -1.234765
qux one 0.081323 -0.268494 0.168016
two -0.898283 -0.218499 1.408028
three -1.267828 -0.689263 0.520995

In [397]: store.append('df_mi', df_mi)

In [398]: store.select('df_mi')
Out[398]:
A B C
foo bar
foo one 0.667450 0.169405 -1.358046
two -0.105563 0.492195 0.076693
three 0.213685 -0.285283 -1.210529
bar one -1.408386 0.941577 -0.342447
two 0.222031 0.052607 2.093214
baz two 1.064908 1.778161 -0.913867
three -0.030004 -0.399846 -1.234765
qux one 0.081323 -0.268494 0.168016
two -0.898283 -0.218499 1.408028
three -1.267828 -0.689263 0.520995

# the levels are automatically included as data columns


In [399]: store.select('df_mi', 'foo=bar')
Out[399]:
A B C
foo bar
bar one -1.408386 0.941577 -0.342447
two 0.222031 0.052607 2.093214

Nota

La indexpalabra clave está reservada y no se puede usar como un nombre de nivel.

Consultando 
Consultando una mesa 
selecty las deleteoperaciones tienen un criterio opcional que se puede especificar para
seleccionar / eliminar solo un subconjunto de los datos. Esto le permite a uno tener una tabla en
disco muy grande y recuperar solo una parte de los datos.

Una consulta se especifica utilizando la Termclase debajo del capó, como una expresión booleana.

 indexy columnsson indexadores compatibles de DataFrames.


 si data_columnsse especifican, se pueden usar como indexadores adicionales.
 nombre del nivel en un MultiIndex, con el nombre por defecto level_0, level_1... si no
proporcionada.
Los operadores de comparación válidos son:

=, ==, !=, >, >=, <, <=

Las expresiones booleanas válidas se combinan con:

 | : o
 & : y
 (y ): para agrupar
Estas reglas son similares a cómo se usan las expresiones booleanas en los pandas para la
indexación.

Nota

 = se expandirá automáticamente al operador de comparación ==


 ~ no es el operador, pero solo se puede usar en circunstancias muy limitadas
 Si se pasa una lista / tupla de expresiones, se combinarán mediante &
Las siguientes son expresiones válidas:

 'index >= date'
 "columns = ['A', 'D']"
 "columns in ['A', 'D']"
 'columns = A'
 'columns == A'
 "~(columns = ['A', 'B'])"
 'index > df.index[3] & string = "bar"'
 '(index > df.index[3] & index <= df.index[6]) | string = "bar"'
 "ts >= Timestamp('2012-02-01')"
 "major_axis>=20130101"
El indexersestán en el lado izquierdo de la sub-expresión:

columns` major_axis`ts

El lado derecho de la subexpresión (después de un operador de comparación) puede ser:


 funciones que se evaluarán, p. ej. Timestamp('2012-02-01')
 cadenas, p. ej. "bar"
 como fecha, por ejemplo 20130101, o"20130101"
 listas, por ejemplo "['A', 'B']"
 variables que se definen en el espacio de nombres locales, por ejemplo date

Nota

No se recomienda pasar una cadena a una consulta interpolando en la expresión de


consulta. Simplemente asigne la cadena de interés a una variable y use esa variable en una
expresión. Por ejemplo, haz esto

string = "HolyMoly'"
store.select('df', 'index == string')

en lugar de esto

string = "HolyMoly'"
store.select('df', 'index == %s' % string)

Este último no funcionará y generará una SyntaxError.Nota que hay una comilla simple seguida de
una comilla doble en la string variable.

Si debe interpolar, use el '%r'especificador de formato

store.select('df', 'index == %r' % string)

que se cita string.
Aquí hay unos ejemplos:

In [400]: dfq = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD'),


.....: index=pd.date_range('20130101', periods=10))
.....:

In [401]: store.append('dfq', dfq, format='table', data_columns=True)

Utilice expresiones booleanas, con evaluación de funciones en línea.

In [402]: store.select('dfq', "index>pd.Timestamp('20130104') & columns=['A', 'B']")


Out[402]:
A B
2013-01-05 -1.083889 0.811865
2013-01-06 -0.402227 1.618922
2013-01-07 0.948196 0.183573
2013-01-08 -1.043530 -0.708145
2013-01-09 0.813949 1.508891
2013-01-10 1.176488 -1.246093

Usar referencia de columna en línea.

In [403]: store.select('dfq', where="A>0 or C>0")


Out[403]:
A B C D
2013-01-01 0.620028 0.159416 -0.263043 -0.639244
2013-01-04 -0.536722 1.005707 0.296917 0.139796
2013-01-05 -1.083889 0.811865 1.648435 -0.164377
2013-01-07 0.948196 0.183573 0.145277 0.308146
2013-01-08 -1.043530 -0.708145 1.430905 -0.850136
2013-01-09 0.813949 1.508891 -1.556154 0.187597
2013-01-10 1.176488 -1.246093 -0.002726 -0.444249

La columnspalabra clave se puede suministrar para seleccionar una lista de columnas para devolver,
esto es equivalente a pasar un 'columns=list_of_columns_to_filter' :

In [404]: store.select('df', "columns=['A', 'B']")


Out[404]:
A B
2000-01-01 1.334065 0.521036
2000-01-02 -1.613932 1.088104
2000-01-03 -0.585314 -0.275038
2000-01-04 0.632369 -1.249657
2000-01-05 1.060617 -0.143682
2000-01-06 3.050329 1.317933
2000-01-07 -0.539452 -0.771133
2000-01-08 0.649464 -1.736427

starty los stopparámetros se pueden especificar para limitar el espacio total de búsqueda. Estos


son en términos del número total de filas en una tabla.

Nota

selectgenerará un ValueErrorsi la expresión de consulta tiene una referencia de variable


desconocida. Por lo general, esto significa que está intentando seleccionar en una columna
que no es una columna de datos.

selectgenerará un SyntaxErrorsi la expresión de consulta no es válida.


Consulta timedelta64 [ns] 
Puede almacenar y consultar utilizando el timedelta64[ns]tipo. Los términos se pueden especificar
en el formato:, <float>(<unit>)donde flotante puede estar firmado (y fraccionado), y la unidad
puede ser D,s,ms,us,nspara el timedelta. Aquí hay un ejemplo:

In [405]: from datetime import timedelta

In [406]: dftd = pd.DataFrame({'A': pd.Timestamp('20130101'),


.....: 'B': [pd.Timestamp('20130101') + timedelta(days=i,
.....: seconds=10)
.....: for i in range(10)]})
.....:

In [407]: dftd['C'] = dftd['A'] - dftd['B']

In [408]: dftd
Out[408]:
A B C
0 2013-01-01 2013-01-01 00:00:10 -1 days +23:59:50
1 2013-01-01 2013-01-02 00:00:10 -2 days +23:59:50
2 2013-01-01 2013-01-03 00:00:10 -3 days +23:59:50
3 2013-01-01 2013-01-04 00:00:10 -4 days +23:59:50
4 2013-01-01 2013-01-05 00:00:10 -5 days +23:59:50
5 2013-01-01 2013-01-06 00:00:10 -6 days +23:59:50
6 2013-01-01 2013-01-07 00:00:10 -7 days +23:59:50
7 2013-01-01 2013-01-08 00:00:10 -8 days +23:59:50
8 2013-01-01 2013-01-09 00:00:10 -9 days +23:59:50
9 2013-01-01 2013-01-10 00:00:10 -10 days +23:59:50

In [409]: store.append('dftd', dftd, data_columns=True)

In [410]: store.select('dftd', "C<'-3.5D'")


Out[410]:
A B C
4 2013-01-01 2013-01-05 00:00:10 -5 days +23:59:50
5 2013-01-01 2013-01-06 00:00:10 -6 days +23:59:50
6 2013-01-01 2013-01-07 00:00:10 -7 days +23:59:50
7 2013-01-01 2013-01-08 00:00:10 -8 days +23:59:50
8 2013-01-01 2013-01-09 00:00:10 -9 days +23:59:50
9 2013-01-01 2013-01-10 00:00:10 -10 days +23:59:50

Consultar MultiIndex 
La selección de a MultiIndexse puede lograr utilizando el nombre del nivel.
In [411]: df_mi.index.names
Out[411]: FrozenList(['foo', 'bar'])

In [412]: store.select('df_mi', "foo=baz and bar=two")


Out[412]:
A B C
foo bar
baz two 1.064908 1.778161 -0.913867

Si los MultiIndexnombres de los niveles son None, los niveles están disponibles automáticamente a


través de la level_npalabra clave con nel nivel del MultiIndexque desea seleccionar.

In [413]: index = pd.MultiIndex(


.....: levels=[["foo", "bar", "baz", "qux"], ["one", "two", "three"]],
.....: codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]],
.....: )
.....:

In [414]: df_mi_2 = pd.DataFrame(np.random.randn(10, 3),


.....: index=index, columns=["A", "B", "C"])
.....:

In [415]: df_mi_2
Out[415]:
A B C
foo one 0.856838 1.491776 0.001283
two 0.701816 -1.097917 0.102588
three 0.661740 0.443531 0.559313
bar one -0.459055 -1.222598 -0.455304
two -0.781163 0.826204 -0.530057
baz two 0.296135 1.366810 1.073372
three -0.994957 0.755314 2.119746
qux one -2.628174 -0.089460 -0.133636
two 0.337920 -0.634027 0.421107
three 0.604303 1.053434 1.109090

In [416]: store.append("df_mi_2", df_mi_2)

# the levels are automatically included as data columns with keyword level_n
In [417]: store.select("df_mi_2", "level_0=foo and level_1=two")
Out[417]:
A B C
foo two 0.701816 -1.097917 0.102588
Indexación 
Puede crear / modificar un índice para una tabla create_table_index después de que los datos ya
estén en la tabla (después y append/put operación). Se recomienda crear un índice de tabla . Esto
acelerará mucho sus consultas cuando use un selectcon la dimensión indexada como where.

Nota

Los índices se crean automáticamente en las indexables y en cualquier columna de datos que
especifique. Este comportamiento se puede desactivar pasando index=Falsea append.

# we have automagically already created an index (in the first section)


In [418]: i = store.root.df.table.cols.index.index

In [419]: i.optlevel, i.kind


Out[419]: (6, 'medium')

# change an index by passing new parameters


In [420]: store.create_table_index('df', optlevel=9, kind='full')

In [421]: i = store.root.df.table.cols.index.index

In [422]: i.optlevel, i.kind


Out[422]: (9, 'full')

A menudo, al agregar grandes cantidades de datos a una tienda, es útil desactivar la creación de
índice para cada anexo y luego volver a crearlo al final.

In [423]: df_1 = pd.DataFrame(np.random.randn(10, 2), columns=list('AB'))

In [424]: df_2 = pd.DataFrame(np.random.randn(10, 2), columns=list('AB'))

In [425]: st = pd.HDFStore('appends.h5', mode='w')

In [426]: st.append('df', df_1, data_columns=['B'], index=False)

In [427]: st.append('df', df_2, data_columns=['B'], index=False)

In [428]: st.get_storer('df').table
Out[428]:
/df/table (Table(20,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
"B": Float64Col(shape=(), dflt=0.0, pos=2)}
byteorder := 'little'
chunkshape := (2730,)

Luego cree el índice cuando termine de agregar.

In [429]: st.create_table_index('df', columns=['B'], optlevel=9, kind='full')

In [430]: st.get_storer('df').table
Out[430]:
/df/table (Table(20,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
"B": Float64Col(shape=(), dflt=0.0, pos=2)}
byteorder := 'little'
chunkshape := (2730,)
autoindex := True
colindexes := {
"B": Index(9, full, shuffle, zlib(1)).is_csi=True}

In [431]: st.close()

Vea aquí cómo crear un índice completamente ordenado (CSI) en una tienda existente.

Consulta a través de columnas de datos 


Puede designar (e indexar) ciertas columnas que desea poder realizar consultas (que no sean
las columnas indexables , que siempre puede consultar). Por ejemplo, digamos que desea realizar
esta operación común, en el disco, y devolver solo el marco que coincide con esta consulta. Puede
especificar forzar que todas las columnas sean .data_columns = Truedata_columns

In [432]: df_dc = df.copy()

In [433]: df_dc['string'] = 'foo'

In [434]: df_dc.loc[df_dc.index[4:6], 'string'] = np.nan

In [435]: df_dc.loc[df_dc.index[7:9], 'string'] = 'bar'

In [436]: df_dc['string2'] = 'cool'

In [437]: df_dc.loc[df_dc.index[1:3], ['B', 'C']] = 1.0

In [438]: df_dc
Out[438]:
A B C string string2
2000-01-01 1.334065 0.521036 0.930384 foo cool
2000-01-02 -1.613932 1.000000 1.000000 foo cool
2000-01-03 -0.585314 1.000000 1.000000 foo cool
2000-01-04 0.632369 -1.249657 0.975593 foo cool
2000-01-05 1.060617 -0.143682 0.218423 NaN cool
2000-01-06 3.050329 1.317933 -0.963725 NaN cool
2000-01-07 -0.539452 -0.771133 0.023751 foo cool
2000-01-08 0.649464 -1.736427 0.197288 bar cool

# on-disk operations
In [439]: store.append('df_dc', df_dc, data_columns=['B', 'C', 'string', 'string2'])

In [440]: store.select('df_dc', where='B > 0')


Out[440]:
A B C string string2
2000-01-01 1.334065 0.521036 0.930384 foo cool
2000-01-02 -1.613932 1.000000 1.000000 foo cool
2000-01-03 -0.585314 1.000000 1.000000 foo cool
2000-01-06 3.050329 1.317933 -0.963725 NaN cool

# getting creative
In [441]: store.select('df_dc', 'B > 0 & C > 0 & string == foo')
Out[441]:
A B C string string2
2000-01-01 1.334065 0.521036 0.930384 foo cool
2000-01-02 -1.613932 1.000000 1.000000 foo cool
2000-01-03 -0.585314 1.000000 1.000000 foo cool

# this is in-memory version of this type of selection


In [442]: df_dc[(df_dc.B > 0) & (df_dc.C > 0) & (df_dc.string == 'foo')]
Out[442]:
A B C string string2
2000-01-01 1.334065 0.521036 0.930384 foo cool
2000-01-02 -1.613932 1.000000 1.000000 foo cool
2000-01-03 -0.585314 1.000000 1.000000 foo cool

# we have automagically created this index and the B/C/string/string2


# columns are stored separately as ``PyTables`` columns
In [443]: store.root.df_dc.table
Out[443]:
/df_dc/table (Table(8,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
"B": Float64Col(shape=(), dflt=0.0, pos=2),
"C": Float64Col(shape=(), dflt=0.0, pos=3),
"string": StringCol(itemsize=3, shape=(), dflt=b'', pos=4),
"string2": StringCol(itemsize=4, shape=(), dflt=b'', pos=5)}
byteorder := 'little'
chunkshape := (1680,)
autoindex := True
colindexes := {
"index": Index(6, medium, shuffle, zlib(1)).is_csi=False,
"B": Index(6, medium, shuffle, zlib(1)).is_csi=False,
"C": Index(6, medium, shuffle, zlib(1)).is_csi=False,
"string": Index(6, medium, shuffle, zlib(1)).is_csi=False,
"string2": Index(6, medium, shuffle, zlib(1)).is_csi=False}

Hay una cierta degradación del rendimiento al hacer muchas columnas en columnas de datos , por
lo que corresponde al usuario designarlas. Además, no puede cambiar las columnas de datos (ni
indexables) después de la primera operación de agregar / poner (¡Por supuesto, simplemente
puede leer los datos y crear una nueva tabla!).

Iterador 
Puede pasar iterator=Trueo chunksize=number_in_a_chunk hacia selecty select_as_multiplepara
devolver un iterador en los resultados. El valor predeterminado es 50,000 filas devueltas en un
fragmento.

In [444]: for df in store.select('df', chunksize=3):


.....: print(df)
.....:
A B C
2000-01-01 1.334065 0.521036 0.930384
2000-01-02 -1.613932 1.088104 -0.632963
2000-01-03 -0.585314 -0.275038 -0.937512
A B C
2000-01-04 0.632369 -1.249657 0.975593
2000-01-05 1.060617 -0.143682 0.218423
2000-01-06 3.050329 1.317933 -0.963725
A B C
2000-01-07 -0.539452 -0.771133 0.023751
2000-01-08 0.649464 -1.736427 0.197288

Nota

También puede usar el iterador con el read_hdfque se abrirá, luego cerrará automáticamente la
tienda cuando termine de iterar.
for df in pd.read_hdf('store.h5', 'df', chunksize=3):
print(df)

Tenga en cuenta que la palabra clave chunksize se aplica a las filas de origen . Entonces, si está
haciendo una consulta, el tamaño de fragmento subdividirá el total de filas en la tabla y la consulta
aplicada, devolviendo un iterador en fragmentos de tamaño potencialmente desiguales.

Aquí hay una receta para generar una consulta y usarla para crear fragmentos de retorno de igual
tamaño.

In [445]: dfeq = pd.DataFrame({'number': np.arange(1, 11)})

In [446]: dfeq
Out[446]:
number
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

In [447]: store.append('dfeq', dfeq, data_columns=['number'])

In [448]: def chunks(l, n):


.....: return [l[i:i + n] for i in range(0, len(l), n)]
.....:

In [449]: evens = [2, 4, 6, 8, 10]

In [450]: coordinates = store.select_as_coordinates('dfeq', 'number=evens')

In [451]: for c in chunks(coordinates, 2):


.....: print(store.select('dfeq', where=c))
.....:
number
1 2
3 4
number
5 6
7 8
number
9 10

Consultas avanzadas 
Seleccione una sola columna 

Para recuperar una sola columna indexable o datos, utilizar el método select_column. Esto, por
ejemplo, le permitirá obtener el índice muy rápidamente. Estos devuelven un Seriesresultado,
indexado por el número de fila. Estos no aceptan actualmente el whereselector.

In [452]: store.select_column('df_dc', 'index')


Out[452]:
0 2000-01-01
1 2000-01-02
2 2000-01-03
3 2000-01-04
4 2000-01-05
5 2000-01-06
6 2000-01-07
7 2000-01-08
Name: index, dtype: datetime64[ns]

In [453]: store.select_column('df_dc', 'string')


Out[453]:
0 foo
1 foo
2 foo
3 foo
4 NaN
5 NaN
6 foo
7 bar
Name: string, dtype: object

Seleccionar coordenadas 

En ocasiones, desea obtener las coordenadas (también conocidas como ubicaciones de índice) de
su consulta. Esto devuelve una Int64Indexde las ubicaciones resultantes. Estas coordenadas
también se pueden pasar a whereoperaciones posteriores .

In [454]: df_coord = pd.DataFrame(np.random.randn(1000, 2),


.....: index=pd.date_range('20000101', periods=1000))
.....:

In [455]: store.append('df_coord', df_coord)

In [456]: c = store.select_as_coordinates('df_coord', 'index > 20020101')

In [457]: c
Out[457]:
Int64Index([732, 733, 734, 735, 736, 737, 738, 739, 740, 741,
...
990, 991, 992, 993, 994, 995, 996, 997, 998, 999],
dtype='int64', length=268)

In [458]: store.select('df_coord', where=c)


Out[458]:
0 1
2002-01-02 -0.165548 0.646989
2002-01-03 0.782753 -0.123409
2002-01-04 -0.391932 -0.740915
2002-01-05 1.211070 -0.668715
2002-01-06 0.341987 -0.685867
... ... ...
2002-09-22 1.788110 -0.405908
2002-09-23 -0.801912 0.768460
2002-09-24 0.466284 -0.457411
2002-09-25 -0.364060 0.785367
2002-09-26 -1.463093 1.187315

[268 rows x 2 columns]

Seleccionar usando una máscara where 

En algún momento su consulta puede implicar la creación de una lista de filas para seleccionar. Por
lo general, esto masksería el resultado indexde una operación de indexación. Este ejemplo
selecciona los meses de un índice de fecha y hora que son 5.

In [459]: df_mask = pd.DataFrame(np.random.randn(1000, 2),


.....: index=pd.date_range('20000101', periods=1000))
.....:

In [460]: store.append('df_mask', df_mask)

In [461]: c = store.select_column('df_mask', 'index')


In [462]: where = c[pd.DatetimeIndex(c).month == 5].index

In [463]: store.select('df_mask', where=where)


Out[463]:
0 1
2000-05-01 1.735883 -2.615261
2000-05-02 0.422173 2.425154
2000-05-03 0.632453 -0.165640
2000-05-04 -1.017207 -0.005696
2000-05-05 0.299606 0.070606
... ... ...
2002-05-27 0.234503 1.199126
2002-05-28 -3.021833 -1.016828
2002-05-29 0.522794 0.063465
2002-05-30 -1.653736 0.031709
2002-05-31 -0.968402 -0.393583

[93 rows x 2 columns]

Objeto de almacenamiento 

Si desea inspeccionar el objeto almacenado, recupérelo mediante get_storer. Podría usar esto


mediante programación para decir obtener el número de filas en un objeto.

In [464]: store.get_storer('df_dc').nrows
Out[464]: 8

Múltiples consultas de tabla 


Los métodos append_to_multipley select_as_multiplepueden realizar anexar / seleccionar de
varias tablas a la vez. La idea es tener una tabla (llámela tabla de selección) que indexe la mayoría /
todas las columnas, y realice sus consultas. Las otras tablas son tablas de datos con un índice que
coincide con el índice de la tabla de selección. A continuación, puede realizar una consulta muy
rápida en la tabla de selección y recuperar muchos datos. Este método es similar a tener una tabla
muy amplia, pero permite consultas más eficientes.

El append_to_multiplemétodo divide un DataFrame individual dado en varias tablas de acuerdo


con dun diccionario que asigna los nombres de las tablas a una lista de 'columnas' que desea en esa
tabla. Si se usa None en lugar de una lista, esa tabla tendrá las columnas restantes no especificadas
del DataFrame dado. El argumento selector define qué tabla es la tabla de selección (desde la que
puede realizar consultas). El argumento dropnaeliminará filas de la entrada DataFramepara garantizar
que las tablas estén sincronizadas. Esto significa que si una fila para una de las tablas que se está
escribiendo es completamente np.NaN, esa fila se eliminará de todas las tablas.
Si dropnaes falso, EL USUARIO ES RESPONSABLE DE SINCRONIZAR LAS TABLAS . Recuerde
que las np.Nanfilas enteras no se escriben en el HDFStore, por lo que si elige llamar dropna=False,
algunas tablas pueden tener más filas que otras y, por select_as_multiplelo tanto, pueden no
funcionar o pueden devolver resultados inesperados.

In [465]: df_mt = pd.DataFrame(np.random.randn(8, 6),


.....: index=pd.date_range('1/1/2000', periods=8),
.....: columns=['A', 'B', 'C', 'D', 'E', 'F'])
.....:

In [466]: df_mt['foo'] = 'bar'

In [467]: df_mt.loc[df_mt.index[1], ('A', 'B')] = np.nan

# you can also create the tables individually


In [468]: store.append_to_multiple({'df1_mt': ['A', 'B'], 'df2_mt': None},
.....: df_mt, selector='df1_mt')
.....:

In [469]: store
Out[469]:
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5

# individual tables were created


In [470]: store.select('df1_mt')
Out[470]:
A B
2000-01-01 1.251079 -0.362628
2000-01-02 NaN NaN
2000-01-03 0.719421 -0.448886
2000-01-04 1.140998 -0.877922
2000-01-05 1.043605 1.798494
2000-01-06 -0.467812 -0.027965
2000-01-07 0.150568 0.754820
2000-01-08 -0.596306 -0.910022

In [471]: store.select('df2_mt')
Out[471]:
C D E F foo
2000-01-01 1.602451 -0.221229 0.712403 0.465927 bar
2000-01-02 -0.525571 0.851566 -0.681308 -0.549386 bar
2000-01-03 -0.044171 1.396628 1.041242 -1.588171 bar
2000-01-04 0.463351 -0.861042 -2.192841 -1.025263 bar
2000-01-05 -1.954845 -1.712882 -0.204377 -1.608953 bar
2000-01-06 1.601542 -0.417884 -2.757922 -0.307713 bar
2000-01-07 -1.935461 1.007668 0.079529 -1.459471 bar
2000-01-08 -1.057072 -0.864360 -1.124870 1.732966 bar

# as a multiple
In [472]: store.select_as_multiple(['df1_mt', 'df2_mt'], where=['A>0', 'B>0'],
.....: selector='df1_mt')
.....:
Out[472]:
A B C D E F foo
2000-01-05 1.043605 1.798494 -1.954845 -1.712882 -0.204377 -1.608953 bar
2000-01-07 0.150568 0.754820 -1.935461 1.007668 0.079529 -1.459471 bar

Eliminar de una tabla 


Puede eliminar de una tabla de forma selectiva especificando a where. Al eliminar filas, es
importante comprender las PyTablesfilas eliminadas borrando las filas y luego moviendo los
siguientes datos. Por lo tanto, eliminar puede ser una operación muy costosa dependiendo de la
orientación de sus datos. Para obtener un rendimiento óptimo, vale la pena tener la dimensión que
está eliminando como la primera indexables.

Los datos se ordenan (en el disco) en términos de indexables. Aquí hay un caso de uso
simple. Usted almacena datos de tipo panel, con fechas en major_axisy ids en minor_axis. Los
datos se entrelazan así:

 fecha_1
o id_1
o id_2
o .
o id_n
 fecha_2
o id_1
o .
o id_n
Debe quedar claro que una operación de eliminación en el major_axisserá bastante rápida, ya que
se elimina un fragmento, luego se mueven los siguientes datos. Por otro lado, una operación de
eliminación en el minor_axisserá muy costosa. En este caso, casi con certeza sería más rápido
reescribir la tabla usando un whereque selecciona todos los datos excepto los que faltan.

Advertencia

Tenga en cuenta que HDF5 NO RECLAMA EL ESPACIO en los archivos h5 automáticamente. Por


lo tanto, eliminar repetidamente (o eliminar nodos) y agregar nuevamente, TENDRÁ A
AUMENTAR EL TAMAÑO DEL ARCHIVO .

Para reempaquetar y limpiar el archivo, use ptrepack .


Notas y advertencias 
Compresión 
PyTablespermite que los datos almacenados sean comprimidos. Esto se aplica a todo tipo de
tiendas, no solo a las mesas. Se utilizan dos parámetros para controlar la
compresión: complevely complib.

complevel Especifica si y qué tan difícil es comprimir los datos.


complevel=0y complevel=Nonedeshabilita la compresión y 0<complevel<10habilita la
compresión.

complibespecifica qué biblioteca de compresión usar. Si nada es


especificó que zlibse usa la biblioteca predeterminada . Una biblioteca de compresión
generalmente se optimiza para obtener buenas tasas de compresión o velocidad y los
resultados dependerán del tipo de datos. El tipo de compresión que elija depende de sus
necesidades y datos específicos. La lista de bibliotecas de compresión compatibles:

 zlib : la biblioteca de compresión predeterminada. Un clásico en términos de


compresión, logra buenas tasas de compresión pero es algo lento.
 lzo : Compresión y descompresión rápidas.
 bzip2 : buenas tasas de compresión.
 blosc : Compresión y descompresión rápidas.

Soporte para compresores blosc alternativos:

o blosc: blosclz Este es el compresor predeterminado parablosc


o blosc: lz4 : un compresor compacto, muy popular y rápido.
o blosc: lz4hc : una versión modificada de LZ4, produce mejores relaciones de
compresión a expensas de la velocidad.
o blosc: snappy : un compresor popular utilizado en muchos lugares.
o blosc: zlib : un clásico; algo más lento que los anteriores, pero logrando
mejores relaciones de compresión.
o blosc: zstd : un códec extremadamente bien equilibrado; Proporciona las
mejores relaciones de compresión entre las anteriores y a una velocidad
razonablemente rápida.
Si complibse define como algo distinto de las bibliotecas enumeradas, ValueErrorse
emite una excepción.

Nota

Si la biblioteca especificada con la complibopción no se encuentra en su plataforma, la


compresión por defecto es zlibsin más preámbulos.
Habilite la compresión para todos los objetos dentro del archivo:
store_compressed = pd.HDFStore('store_compressed.h5', complevel=9,
complib='blosc:blosclz')

O compresión sobre la marcha (esto solo se aplica a tablas) en tiendas donde la


compresión no está habilitada:

store.append('df', df, complib='zlib', complevel=5)

ptrepack 
PyTablesofrece un mejor rendimiento de escritura cuando las tablas se comprimen
después de que se escriben, en lugar de activar la compresión desde el principio. Puede
usar la PyTablesutilidad suministrada ptrepack. Además, ptrepackpuede cambiar los
niveles de compresión después del hecho.

ptrepack --chunkshape=auto --propindexes --complevel=9 --complib=blosc in.h5


out.h5

Además, volverá a empaquetar el archivo para permitirle reutilizar el espacio previamente


eliminado. Alternativamente, uno simplemente puede eliminar el archivo y volver a
escribir, o usar el método.ptrepack in.h5 out.h5copy

Advertencias 
Advertencia

HDFStoreno es seguro para escribir . El subyacente PyTablessolo admite lecturas


concurrentes (a través de subprocesos o procesos). Si necesita leer y escribir al mismo
tiempo , debe serializar estas operaciones en un solo hilo en un solo proceso. Corromperá
sus datos de otra manera. Consulte el ( GH2397 ) para obtener más información.
 Si usa bloqueos para administrar el acceso de escritura entre múltiples procesos,
puede usarlo fsync()antes de liberar bloqueos de escritura. Para su comodidad,
puede store.flush(fsync=True)hacer esto por usted.
 Una vez que tablese crea una columna (DataFrame) se corrigen; solo se pueden
agregar exactamente las mismas columnas
 Tenga en cuenta que las zonas horarias (por
ejemplo, pytz.timezone('US/Eastern')) no son necesariamente iguales en todas las
versiones de zonas horarias. Por lo tanto, si los datos se localizan en una zona
horaria específica en el HDFStore usando una versión de una biblioteca de zonas
horarias y esos datos se actualizan con otra versión, los datos se convertirán a UTC
ya que estas zonas horarias no se consideran iguales. Utilice la misma versión de la
biblioteca de zonas horarias o úsela tz_convertcon la definición actualizada de
zonas horarias.
Advertencia

PyTablesmostrará un NaturalNameWarningsi el nombre de una columna no se puede utilizar


como un selector de atributos. Los identificadores naturales contienen solo letras,
números y guiones bajos, y pueden no comenzar con un número. Otros identificadores no
se pueden usar en una wherecláusula y generalmente son una mala idea.

Tipos de datos 
HDFStoreasignará un dtype de objeto al dtype PyTablessubyacente. Esto significa que se
sabe que funcionan los siguientes tipos:

Tipo Representa valores perdidos


flotante : float64, float32, float16 np.nan
entero: int64, int32, int8, uint64,uint32, uint8
booleano
datetime64[ns] NaT
timedelta64[ns] NaT
categórico: ver la sección a continuación
objeto: strings np.nan
unicodelas columnas no son compatibles y FALLARÁ .

Datos categóricos 
Puede escribir datos que contengan categorydtypes en a HDFStore. Las consultas
funcionan igual que si fuera una matriz de objetos. Sin embargo, los categorydatos
tipificados se almacenan de manera más eficiente.

In [473]: dfcat = pd.DataFrame({'A':


pd.Series(list('aabbcdba')).astype('category'),
.....: 'B': np.random.randn(8)})
.....:

In [474]: dfcat
Out[474]:
A B
0 a 0.477849
1 a 0.283128
2 b -2.045700
3 b -0.338206
4 c -0.423113
5 d 2.314361
6 b -0.033100
7 a -0.965461
In [475]: dfcat.dtypes
Out[475]:
A category
B float64
dtype: object

In [476]: cstore = pd.HDFStore('cats.h5', mode='w')

In [477]: cstore.append('dfcat', dfcat, format='table', data_columns=['A'])

In [478]: result = cstore.select('dfcat', where="A in ['b', 'c']")

In [479]: result
Out[479]:
A B
2 b -2.045700
3 b -0.338206
4 c -0.423113
6 b -0.033100

In [480]: result.dtypes
Out[480]:
A category
B float64
dtype: object

Columnas de cadena 
min_itemsize

La implementación subyacente de HDFStoreutiliza un ancho de columna fijo (itemize) para


columnas de cadena. El tamaño del ítem de una columna de cadena se calcula como el
máximo de la longitud de los datos (para esa columna) que se pasa al HDFStore, en el
primer anexo . Anexos posteriores, puede introducir una cadena para una columna más
grande que la columna puede contener, se generará una excepción (de lo contrario, podría
tener un truncamiento silencioso de estas columnas, lo que provocaría la pérdida de
información). En el futuro podemos relajar esto y permitir que ocurra un truncamiento
especificado por el usuario.

Pase min_itemsizela creación de la primera tabla a a priori y especifique la longitud


mínima de una columna de cadena particular. min_itemsizepuede ser un entero o un dict
que asigna un nombre de columna a un entero. Puede pasar valuescomo clave para
permitir que todas las indexables o data_columns tengan este min_itemsize.
Pasar un min_itemsizedict hará que todas las columnas pasadas
se creen automáticamente como data_columns .

Nota

Si no está pasando ninguna data_columns, entonces min_itemsizeserá el máximo de la


longitud de cualquier cadena pasada

In [481]: dfs = pd.DataFrame({'A': 'foo', 'B': 'bar'}, index=list(range(5)))

In [482]: dfs
Out[482]:
A B
0 foo bar
1 foo bar
2 foo bar
3 foo bar
4 foo bar

# A and B have a size of 30


In [483]: store.append('dfs', dfs, min_itemsize=30)

In [484]: store.get_storer('dfs').table
Out[484]:
/dfs/table (Table(5,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": StringCol(itemsize=30, shape=(2,), dflt=b'', pos=1)}
byteorder := 'little'
chunkshape := (963,)
autoindex := True
colindexes := {
"index": Index(6, medium, shuffle, zlib(1)).is_csi=False}

# A is created as a data_column with a size of 30


# B is size is calculated
In [485]: store.append('dfs2', dfs, min_itemsize={'A': 30})

In [486]: store.get_storer('dfs2').table
Out[486]:
/dfs2/table (Table(5,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": StringCol(itemsize=3, shape=(1,), dflt=b'', pos=1),
"A": StringCol(itemsize=30, shape=(), dflt=b'', pos=2)}
byteorder := 'little'
chunkshape := (1598,)
autoindex := True
colindexes := {
"index": Index(6, medium, shuffle, zlib(1)).is_csi=False,
"A": Index(6, medium, shuffle, zlib(1)).is_csi=False}

nan_rep

Las columnas de cadena serializarán un np.nan(un valor faltante) con


la nan_reprepresentación de cadena. Esto predeterminado es el valor de la
cadena nan. Inadvertidamente podría convertir un nanvalor real en un valor perdido.

In [487]: dfss = pd.DataFrame({'A': ['foo', 'bar', 'nan']})

In [488]: dfss
Out[488]:
A
0 foo
1 bar
2 nan

In [489]: store.append('dfss', dfss)

In [490]: store.select('dfss')
Out[490]:
A
0 foo
1 bar
2 NaN

# here you need to specify a different nan rep


In [491]: store.append('dfss2', dfss, nan_rep='_nan_')

In [492]: store.select('dfss2')
Out[492]:
A
0 foo
1 bar
2 nan

Compatibilidad externa 
HDFStoreescribe tableobjetos de formato en formatos específicos adecuados para
producir viajes de ida y vuelta sin pérdidas a objetos de pandas. Por compatibilidad
externa, HDFStorepuede leer PyTablestablas de formato nativo .

Es posible escribir un HDFStoreobjeto que se pueda importar fácilmente Rusando


la rhdf5biblioteca ( sitio web del paquete ). Cree una tienda de formato de tabla como
esta:

In [493]: df_for_r = pd.DataFrame({"first": np.random.rand(100),


.....: "second": np.random.rand(100),
.....: "class": np.random.randint(0, 2, (100, ))},
.....: index=range(100))
.....:

In [494]: df_for_r.head()
Out[494]:
first second class
0 0.864919 0.852910 0
1 0.030579 0.412962 1
2 0.015226 0.978410 0
3 0.498512 0.686761 0
4 0.232163 0.328185 1

In [495]: store_export = pd.HDFStore('export.h5')

In [496]: store_export.append('df_for_r', df_for_r, data_columns=df_dc.columns)

In [497]: store_export
Out[497]:
<class 'pandas.io.pytables.HDFStore'>
File path: export.h5

En R, este archivo se puede leer en un data.frameobjeto utilizando la rhdf5 biblioteca. La


siguiente función de ejemplo lee los nombres de columna y los valores de datos
correspondientes de los valores y los ensambla en un data.frame:

# Load values and column names for all datasets from corresponding nodes and
# insert them into one data.frame object.

library(rhdf5)

loadhdf5data <- function(h5File) {

listing <- h5ls(h5File)


# Find all data nodes, values are stored in *_values and corresponding column
# titles in *_items
data_nodes <- grep("_values", listing$name)
name_nodes <- grep("_items", listing$name)
data_paths = paste(listing$group[data_nodes], listing$name[data_nodes], sep = "/")
name_paths = paste(listing$group[name_nodes], listing$name[name_nodes], sep = "/")
columns = list()
for (idx in seq(data_paths)) {
# NOTE: matrices returned by h5read have to be transposed to obtain
# required Fortran order!
data <- data.frame(t(h5read(h5File, data_paths[idx])))
names <- t(h5read(h5File, name_paths[idx]))
entry <- data.frame(data)
colnames(entry) <- names
columns <- append(columns, entry)
}

data <- data.frame(columns)

return(data)
}

Ahora puedes importar DataFramea R:

> data = loadhdf5data("transfer.hdf5")


> head(data)
first second class
1 0.4170220047 0.3266449 0
2 0.7203244934 0.5270581 0
3 0.0001143748 0.8859421 1
4 0.3023325726 0.3572698 1
5 0.1467558908 0.9085352 1
6 0.0923385948 0.6233601 1

Nota

La función R enumera todo el contenido del archivo HDF5 y ensambla


el data.frameobjeto de todos los nodos coincidentes, así que use esto solo como punto de
partida si ha almacenado múltiples DataFrameobjetos en un solo archivo HDF5.

Rendimiento 
 tablesformato viene con una penalización de rendimiento de escritura en
comparación con las fixedtiendas. El beneficio es la capacidad de agregar /
eliminar y consultar (cantidades de datos potencialmente muy grandes). Los
tiempos de escritura son generalmente más largos en comparación con las tiendas
regulares. Los tiempos de consulta pueden ser bastante rápidos, especialmente en
un eje indexado.
 Puede pasar chunksize=<int>a append, especificando el tamaño de fragmento de
escritura (el valor predeterminado es 50000). Esto reducirá significativamente el
uso de memoria al escribir.
 Puede pasar expectedrows=<int>al primero append, para establecer el número
TOTAL de filas que PyTablesesperará. Esto optimizará el rendimiento de lectura /
escritura.
 Las filas duplicadas se pueden escribir en las tablas, pero se filtran en la selección
(con los últimos elementos seleccionados; por lo tanto, una tabla es única en pares
mayores y menores)
 Se PerformanceWarninggenerará una A si está intentando almacenar tipos que
serán seleccionados por PyTables (en lugar de almacenarse como tipos
endémicos). Consulte aquí para obtener más información y algunas soluciones.

Pluma 
Feather proporciona serialización en columnas binarias para marcos de datos. Está
diseñado para hacer que la lectura y escritura de marcos de datos sean eficientes, y para
facilitar el intercambio de datos entre lenguajes de análisis de datos.

Feather está diseñado para serializar y deserializar fielmente DataFrames, admitiendo


todos los tipos de pandas, incluidos los tipos de extensión, como categórico y datetime
con tz.

Varias advertencias.

 Esta es una biblioteca más nueva, y el formato, aunque estable, no garantiza que
sea compatible con versiones anteriores.
 El formato NO escribirá un Index, o MultiIndexpara el DataFramey generará un
error si se proporciona uno no predeterminado. Puede .reset_index()almacenar el
índice o .reset_index(drop=True)ignorarlo.
 No se admiten nombres de columna duplicados y nombres de columnas sin
cadenas
 Los tipos no admitidos incluyen Periodtipos de objetos Python reales. Esto
generará un mensaje de error útil en un intento de serialización.
Ver la documentación completa .

In [498]: df = pd.DataFrame({'a': list('abc'),


.....: 'b': list(range(1, 4)),
.....: 'c': np.arange(3, 6).astype('u1'),
.....: 'd': np.arange(4.0, 7.0, dtype='float64'),
.....: 'e': [True, False, True],
.....: 'f': pd.Categorical(list('abc')),
.....: 'g': pd.date_range('20130101', periods=3),
.....: 'h': pd.date_range('20130101', periods=3,
tz='US/Eastern'),
.....: 'i': pd.date_range('20130101', periods=3,
freq='ns')})
.....:

In [499]: df
Out[499]:
a b c d e f g h
i
0 a 1 3 4.0 True a 2013-01-01 2013-01-01 00:00:00-05:00 2013-01-01
00:00:00.000000000
1 b 2 4 5.0 False b 2013-01-02 2013-01-02 00:00:00-05:00 2013-01-01
00:00:00.000000001
2 c 3 5 6.0 True c 2013-01-03 2013-01-03 00:00:00-05:00 2013-01-01
00:00:00.000000002

In [500]: df.dtypes
Out[500]:
a object
b int64
c uint8
d float64
e bool
f category
g datetime64[ns]
h datetime64[ns, US/Eastern]
i datetime64[ns]
dtype: object

Escribe en un archivo de plumas.

In [501]: df.to_feather('example.feather')

Leer de un archivo de plumas.

In [502]: result = pd.read_feather('example.feather')

In [503]: result
Out[503]:
a b c d e f g h
i
0 a 1 3 4.0 True a 2013-01-01 2013-01-01 00:00:00-05:00 2013-01-01
00:00:00.000000000
1 b 2 4 5.0 False b 2013-01-02 2013-01-02 00:00:00-05:00 2013-01-01
00:00:00.000000001
2 c 3 5 6.0 True c 2013-01-03 2013-01-03 00:00:00-05:00 2013-01-01
00:00:00.000000002

# we preserve dtypes
In [504]: result.dtypes
Out[504]:
a object
b int64
c uint8
d float64
e bool
f category
g datetime64[ns]
h datetime64[ns, US/Eastern]
i datetime64[ns]
dtype: object

Parquet 
Nuevo en la versión 0.21.0.

Apache Parquet proporciona una serialización columnar binaria particionada para marcos


de datos. Está diseñado para hacer que la lectura y escritura de marcos de datos sean
eficientes, y para facilitar el intercambio de datos entre lenguajes de análisis de
datos. Parquet puede usar una variedad de técnicas de compresión para reducir el tamaño
del archivo tanto como sea posible, manteniendo un buen rendimiento de lectura.

Parquet está diseñado para serializar y DataFramedeserializar fielmente s, admitiendo


todos los tipos de pandas, incluidos los tipos de extensión como datetime con tz.

Varias advertencias.

 No se admiten nombres de columna duplicados y nombres de columnas sin


cadenas.
 El pyarrowmotor siempre escribe el índice en la salida, pero fastparquetsolo
escribe índices no predeterminados. Esta columna adicional puede causar
problemas a los consumidores que no son Pandas y que no lo esperan. Puede
forzar la inclusión u omisión de índices con el indexargumento,
independientemente del motor subyacente.
 Los nombres de nivel de índice, si se especifican, deben ser cadenas.
 En el pyarrowmotor, los tipos categóricos para los tipos que no son de cadena se
pueden serializar en parquet, pero se des serializarán como su tipo primitivo.
 El pyarrowmotor conserva el orderedindicador de tipos categóricos con tipos de
cadena. fastparquetNo conserva la orderedbandera.
 Los tipos no admitidos incluyen Intervaltipos de objetos Python reales. Esto
generará un mensaje de error útil en un intento de serialización. Periodtipo es
compatible con pyarrow> = 0.16.0.
 El pyarrowmotor conserva los tipos de datos de extensión, como el número entero
anulable y el tipo de datos de cadena (requiere pyarrow> = 0.16.0 y requiere que
el tipo de extensión implemente los protocolos necesarios, consulte
la documentación de tipos de extensión ).
Puede especificar un enginepara dirigir la serialización. Este puede ser uno de pyarrow,
o fastparquet, o auto. Si el motor NO está especificado, entonces
la pd.options.io.parquet.engineopción está marcada; si esto también es así auto,
entonces pyarrowse intenta y vuelve a caer fastparquet.

Consulte la documentación de pyarrow y fastparquet .

Nota

Estos motores son muy similares y deberían leer / escribir archivos de formato de parquet
casi idénticos. Actualmente pyarrowno admite datos
timedelta, fastparquet>=0.1.4admite fechas y horas con reconocimiento de zona
horaria. Estas bibliotecas difieren al tener diferentes dependencias subyacentes
( fastparquetmediante el uso numba, mientras que pyarrowutiliza una biblioteca c).

In [505]: df = pd.DataFrame({'a': list('abc'),


.....: 'b': list(range(1, 4)),
.....: 'c': np.arange(3, 6).astype('u1'),
.....: 'd': np.arange(4.0, 7.0, dtype='float64'),
.....: 'e': [True, False, True],
.....: 'f': pd.date_range('20130101', periods=3),
.....: 'g': pd.date_range('20130101', periods=3,
tz='US/Eastern'),
.....: 'h': pd.Categorical(list('abc')),
.....: 'i': pd.Categorical(list('abc'), ordered=True)})
.....:

In [506]: df
Out[506]:
a b c d e f g h i
0 a 1 3 4.0 True 2013-01-01 2013-01-01 00:00:00-05:00 a a
1 b 2 4 5.0 False 2013-01-02 2013-01-02 00:00:00-05:00 b b
2 c 3 5 6.0 True 2013-01-03 2013-01-03 00:00:00-05:00 c c

In [507]: df.dtypes
Out[507]:
a object
b int64
c uint8
d float64
e bool
f datetime64[ns]
g datetime64[ns, US/Eastern]
h category
i category
dtype: object

Escribir en un archivo de parquet.

In [508]: df.to_parquet('example_pa.parquet', engine='pyarrow')

In [509]: df.to_parquet('example_fp.parquet', engine='fastparquet')

Leer de un archivo de parquet.

In [510]: result = pd.read_parquet('example_fp.parquet', engine='fastparquet')

In [511]: result = pd.read_parquet('example_pa.parquet', engine='pyarrow')

In [512]: result.dtypes
Out[512]:
a object
b int64
c uint8
d float64
e bool
f datetime64[ns]
g datetime64[ns, US/Eastern]
h category
i category
dtype: object

Lea solo ciertas columnas de un archivo de parquet.

In [513]: result = pd.read_parquet('example_fp.parquet',


.....: engine='fastparquet', columns=['a', 'b'])
.....:

In [514]: result = pd.read_parquet('example_pa.parquet',


.....: engine='pyarrow', columns=['a', 'b'])
.....:
In [515]: result.dtypes
Out[515]:
a object
b int64
dtype: object

Manejo de índices 
Serializar un DataFrameparquet puede incluir el índice implícito como una o más columnas
en el archivo de salida. Por lo tanto, este código:

In [516]: df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})

In [517]: df.to_parquet('test.parquet', engine='pyarrow')

crea un archivo de parquet con tres columnas si se utiliza pyarrowpara la serialización: a, b,


y __index_level_0__. Si está utilizando fastparquet, el índice puede o no escribirse en el
archivo.

Esta columna adicional inesperada hace que algunas bases de datos como Amazon
Redshift rechacen el archivo, porque esa columna no existe en la tabla de destino.

Si desea omitir los índices de un marco de datos al escribir,


pase index=Falsea to_parquet():

In [518]: df.to_parquet('test.parquet', index=False)

Esto crea un archivo de parquet con solo las dos columnas


esperadas, ay b. Si DataFrametiene un índice personalizado, no lo recuperará cuando
cargue este archivo en un DataFrame.

Pasando index=Trueserá siempre escribir el índice, incluso si ese no es el comportamiento


predeterminado del motor subyacente.

Particionando archivos de Parquet 


Nuevo en la versión 0.24.0.

Parquet admite la partición de datos en función de los valores de una o más columnas.

In [519]: df = pd.DataFrame({'a': [0, 0, 1, 1], 'b': [0, 1, 0, 1]})


In [520]: df.to_parquet(path='test', engine='pyarrow',
.....: partition_cols=['a'], compression=None)
.....:

La ruta especifica el directorio principal en el que se guardarán los


datos. Los partition_cols son los nombres de columna por el cual se repartió el conjunto de
datos. Las columnas se dividen en el orden en que se dan. Las divisiones de partición
están determinadas por los valores únicos en las columnas de partición. El ejemplo
anterior crea un conjunto de datos particionado que puede verse así:

test
├── a=0
│ ├── 0bac803e32dc42ae83fddfd029cbdebc.parquet
│ └── ...
└── a=1
├── e6ab24a4f45147b49b54a662f0c412a3.parquet
└── ...

ORC 
Nuevo en la versión 1.0.0.

Similar al formato de parquet , el formato ORC es una serialización columnar binaria para
marcos de datos. Está diseñado para hacer que la lectura de marcos de datos sea
eficiente. Pandas proporciona solamente un lector para el formato de
ORC, read_orc(). Esto requiere la biblioteca pyarrow .

Consultas SQL 
El pandas.io.sqlmódulo proporciona una colección de contenedores de consultas para
facilitar la recuperación de datos y para reducir la dependencia de la API específica de
DB. SQLAlchemy proporciona la abstracción de la base de datos si está instalada. Además,
necesitará una biblioteca de controladores para su base de datos. Ejemplos de tales
controladores son psycopg2 para PostgreSQL o pymysql para MySQL. Para SQLite, esto
se incluye en la biblioteca estándar de Python de forma predeterminada. Puede encontrar
una descripción general de los controladores compatibles para cada dialecto SQL en
los documentos de SQLAlchemy .

Si SQLAlchemy no está instalado, solo se proporciona un respaldo para sqlite (y para


mysql para la compatibilidad con versiones anteriores, pero esto está en desuso y se
eliminará en una versión futura). Este modo requiere un adaptador de base de datos
Python que respete la API de Python DB .
Vea también algunos ejemplos de libros de cocina para algunas estrategias avanzadas.

Las funciones clave son:

read_sql_table(nombre_tabla, con [, Lea la tabla de la base de datos SQL en un DataFrame


esquema, ...])
read_sql_query(sql, con [, index_col, ...]) Leer consulta SQL en un DataFrame.
read_sql(sql, con [, index_col, ...]) Lea la tabla de consulta o base de datos SQL en un Da
DataFrame.to_sql(self, name, con [, schema, ...]) Escribir registros almacenados en un DataFrame en un
datos SQL.

Nota

La función read_sql()es una envoltura conveniente read_sql_table()y read_sql_query()


(y para compatibilidad con versiones anteriores) y delegará a una función específica
dependiendo de la entrada proporcionada (nombre de la tabla de base de datos o consulta
sql). Los nombres de tabla no necesitan ser citados si tienen caracteres especiales.
En el siguiente ejemplo, usamos el motor de base de datos SQL SQlite . Puede usar una
base de datos temporal de SQLite donde los datos se almacenan en "memoria".

Para conectarse con SQLAlchemy, utiliza la create_engine()función para crear un objeto


de motor a partir del URI de la base de datos. Solo necesita crear el motor una vez por
base de datos a la que se está conectando. Para obtener más
información create_engine()y el formato de URI, consulte los ejemplos a continuación y
la documentación de SQLAlchemy

In [521]: from sqlalchemy import create_engine

# Create your engine.


In [522]: engine = create_engine('sqlite:///:memory:')

Si desea administrar sus propias conexiones, puede pasar una de ellas:

with engine.connect() as conn, conn.begin():


data = pd.read_sql_table('data', conn)

Escribir marcos de datos 


Suponiendo que los siguientes datos están en a DataFrame data, podemos insertarlos en la
base de datos usando to_sql().

carné de identidad Fecha Col_1 Col_2 Col_


26 2012-10-18 X 25,7 Cier
42 2012-10-19 Y -12,4 Fals
carné de identidad Fecha Col_1 Col_2 Col_
63 2012-10-20 Z 5,73 Cier
In [523]: data
Out[523]:
id Date Col_1 Col_2 Col_3
0 26 2010-10-18 X 27.50 True
1 42 2010-10-19 Y -12.50 False
2 63 2010-10-20 Z 5.73 True

In [524]: data.to_sql('data', engine)

Con algunas bases de datos, escribir DataFrames grandes puede provocar errores debido
a que se exceden las limitaciones de tamaño de paquete. Esto se puede evitar
configurando el chunksizeparámetro al llamar to_sql. Por ejemplo, lo siguiente
escribe dataen la base de datos en lotes de 1000 filas a la vez:

In [525]: data.to_sql('data_chunked', engine, chunksize=1000)

Tipos de datos SQL 


to_sql()intentará asignar sus datos a un tipo de datos SQL apropiado basado en el tipo
de datos. Cuando tienes columnas de dtype object, los pandas intentarán inferir el tipo de
datos.

Siempre puede anular el tipo predeterminado especificando el tipo SQL deseado de


cualquiera de las columnas utilizando el dtypeargumento. Este argumento necesita un
diccionario que asigne nombres de columna a tipos SQLAlchemy (o cadenas para el modo
de respaldo sqlite3). Por ejemplo, especificando el uso del Stringtipo sqlalchemy en lugar
del Texttipo predeterminado para columnas de cadena:

In [526]: from sqlalchemy.types import String

In [527]: data.to_sql('data_dtype', engine, dtype={'Col_1': String})

Nota

Debido al soporte limitado para timedelta's en los diferentes tipos de bases de datos, las
columnas con tipo timedelta64se escribirán como valores enteros como nanosegundos en
la base de datos y se generará una advertencia.

Nota

Las columnas de categorydtype se convertirán a la representación densa como se


obtendría np.asarray(categorical)(por ejemplo, para las categorías de cadenas, esto
proporciona una serie de cadenas). Debido a esto, la lectura de la tabla de la base de datos
nuevamente no genera un valor categórico.

Tipos de datos de fecha y hora 


Utilizando SQLAlchemy, to_sql()es capaz de escribir datos de fecha y hora que son
ingenuos o conscientes de la zona horaria. Sin embargo, los datos resultantes
almacenados en la base de datos dependen en última instancia del tipo de datos
admitidos para los datos de fecha y hora del sistema de base de datos que se utiliza.

La siguiente tabla enumera los tipos de datos admitidos para datos de fecha y hora para
algunas bases de datos comunes. Otros dialectos de bases de datos pueden tener
diferentes tipos de datos para datos de fecha y hora.

Base de datos Tipos de fecha y hora de SQL Soporte de zona horaria


SQLite TEXT No
MySQL TIMESTAMP o DATETIME No
PostgreSQL TIMESTAMP o TIMESTAMP WITH TIME ZONE si
Al escribir datos conscientes de la zona horaria en bases de datos que no admiten zonas
horarias, los datos se escribirán como marcas de tiempo ingenuas de la zona horaria que
están en la hora local con respecto a la zona horaria.

read_sql_table()también es capaz de leer datos de fecha y hora que son conscientes de


la zona horaria o ingenuos. Al leer tipos, los pandas convertirán los datos a
UTC.TIMESTAMP WITH TIME ZONE

Método de inserción 
Nuevo en la versión 0.24.0.

El parámetro methodcontrola la cláusula de inserción de SQL utilizada. Los valores posibles


son:

 None: Utiliza la INSERTcláusula SQL estándar (una por fila).


 'multi': Pase múltiples valores en una sola INSERTcláusula. Utiliza una sintaxis
SQL especial que no es compatible con todos los backends. Esto generalmente
proporciona un mejor rendimiento para bases de datos analíticas
como Presto y Redshift , pero tiene un rendimiento peor para el backend SQL
tradicional si la tabla contiene muchas columnas. Para obtener más información,
consulte la documentación de SQLAlchemy .
 invocable con firma : Esto se puede usar para implementar un método de inserción
más eficaz basado en características de dialecto de backend específicas.
(pd_table, conn, keys, data_iter)
Ejemplo de invocable mediante la cláusula COPY de PostgreSQL :
# Alternative to_sql() *method* for DBs that support COPY FROM
import csv
from io import StringIO

def psql_insert_copy(table, conn, keys, data_iter):


"""
Execute SQL statement inserting data

Parameters
----------
table : pandas.io.sql.SQLTable
conn : sqlalchemy.engine.Engine or sqlalchemy.engine.Connection
keys : list of str
Column names
data_iter : Iterable that iterates the values to be inserted
"""
# gets a DBAPI connection that can provide a cursor
dbapi_conn = conn.connection
with dbapi_conn.cursor() as cur:
s_buf = StringIO()
writer = csv.writer(s_buf)
writer.writerows(data_iter)
s_buf.seek(0)

columns = ', '.join('"{}"'.format(k) for k in keys)


if table.schema:
table_name = '{}.{}'.format(table.schema, table.name)
else:
table_name = table.name

sql = 'COPY {} ({}) FROM STDIN WITH CSV'.format(


table_name, columns)
cur.copy_expert(sql=sql, file=s_buf)

Tablas de lectura 
read_sql_table() leerá una tabla de base de datos con el nombre de la tabla y,
opcionalmente, un subconjunto de columnas para leer.

Nota

Para usar read_sql_table(), debe tener instalada la dependencia opcional SQLAlchemy.

In [528]: pd.read_sql_table('data', engine)


Out[528]:
index id Date Col_1 Col_2 Col_3
0 0 26 2010-10-18 X 27.50 True
1 1 42 2010-10-19 Y -12.50 False
2 2 63 2010-10-20 Z 5.73 True

Nota

Tenga en cuenta que pandas infiere tipos de columna de los resultados de la consulta y no
busca tipos de datos en el esquema físico de la base de datos. Por ejemplo, suponga
que userid es una columna entera en una tabla. Luego, intuitivamente, devolverá series
con valores enteros, mientras que devolverá series con valores de objetos (str). En
consecuencia, si el resultado de la consulta está vacío, todas las columnas resultantes se
devolverán como valor de objeto (ya que son más generales). Si prevé que su consulta a
veces generará un resultado vacío, es posible que desee escribir de forma explícita
después para garantizar la integridad de
dtype.select userid ...select cast(userid as text) ...
También puede especificar el nombre de la columna como DataFrameíndice y especificar
un subconjunto de columnas para leer.

In [529]: pd.read_sql_table('data', engine, index_col='id')


Out[529]:
index Date Col_1 Col_2 Col_3
id
26 0 2010-10-18 X 27.50 True
42 1 2010-10-19 Y -12.50 False
63 2 2010-10-20 Z 5.73 True

In [530]: pd.read_sql_table('data', engine, columns=['Col_1', 'Col_2'])


Out[530]:
Col_1 Col_2
0 X 27.50
1 Y -12.50
2 Z 5.73

Y puede forzar explícitamente que las columnas se analicen como fechas:

In [531]: pd.read_sql_table('data', engine, parse_dates=['Date'])


Out[531]:
index id Date Col_1 Col_2 Col_3
0 0 26 2010-10-18 X 27.50 True
1 1 42 2010-10-19 Y -12.50 False
2 2 63 2010-10-20 Z 5.73 True
Si es necesario, puede especificar explícitamente una cadena de formato, o un dict de
argumentos para pasar a pandas.to_datetime():

pd.read_sql_table('data', engine, parse_dates={'Date': '%Y-%m-%d'})


pd.read_sql_table('data', engine,
parse_dates={'Date': {'format': '%Y-%m-%d %H:%M:%S'}})

Puede verificar si existe una tabla usando has_table()

Soporte de esquema 
La lectura y escritura de diferentes esquemas se admite a través de la schema palabra clave
en las funciones read_sql_table()y to_sql(). Sin embargo, tenga en cuenta que esto
depende del sabor de la base de datos (sqlite no tiene esquemas). Por ejemplo:

df.to_sql('table', engine, schema='other_schema')


pd.read_sql_table('table', engine, schema='other_schema')

Consultando 
Puede consultar utilizando SQL sin formato en la read_sql_query()función. En este caso,
debe usar la variante SQL adecuada para su base de datos. Al usar SQLAlchemy, también
puede pasar construcciones de lenguaje de expresión SQLAlchemy, que son
independientes de la base de datos.

In [532]: pd.read_sql_query('SELECT * FROM data', engine)


Out[532]:
index id Date Col_1 Col_2 Col_3
0 0 26 2010-10-18 00:00:00.000000 X 27.50 1
1 1 42 2010-10-19 00:00:00.000000 Y -12.50 0
2 2 63 2010-10-20 00:00:00.000000 Z 5.73 1

Por supuesto, puede especificar una consulta más "compleja".

In [533]: pd.read_sql_query("SELECT id, Col_1, Col_2 FROM data WHERE id = 42;",


engine)
Out[533]:
id Col_1 Col_2
0 42 Y -12.5

La read_sql_query()función admite un chunksizeargumento. Al especificar esto, se


devolverá un iterador a través de fragmentos del resultado de la consulta:
In [534]: df = pd.DataFrame(np.random.randn(20, 3), columns=list('abc'))

In [535]: df.to_sql('data_chunks', engine, index=False)

In [536]: for chunk in pd.read_sql_query("SELECT * FROM data_chunks",


.....: engine, chunksize=5):
.....: print(chunk)
.....:
a b c
0 0.092961 -0.674003 1.104153
1 -0.092732 -0.156246 -0.585167
2 -0.358119 -0.862331 -1.672907
3 0.550313 -1.507513 -0.617232
4 0.650576 1.033221 0.492464
a b c
0 -1.627786 -0.692062 1.039548
1 -1.802313 -0.890905 -0.881794
2 0.630492 0.016739 0.014500
3 -0.438358 0.647275 -0.052075
4 0.673137 1.227539 0.203534
a b c
0 0.861658 0.867852 -0.465016
1 1.547012 -0.947189 -1.241043
2 0.070470 0.901320 0.937577
3 0.295770 1.420548 -0.005283
4 -1.518598 -0.730065 0.226497
a b c
0 -2.061465 0.632115 0.853619
1 2.719155 0.139018 0.214557
2 -1.538924 -0.366973 -0.748801
3 -0.478137 -1.559153 -3.097759
4 -2.320335 -0.221090 0.119763

También puede ejecutar una consulta simple sin crear un DataFramecon execute(). Esto es


útil para consultas que no devuelven valores, como INSERT. Esto es funcionalmente
equivalente a llamar executeal motor SQLAlchemy o al objeto de conexión
db. Nuevamente, debe usar la variante de sintaxis SQL apropiada para su base de datos.

from pandas.io import sql


sql.execute('SELECT * FROM table_name', engine)
sql.execute('INSERT INTO table_name VALUES(?, ?, ?)', engine,
params=[('id', 1, 12.2, True)])

Ejemplos de conexión del motor 


Para conectarse con SQLAlchemy, utiliza la create_engine()función para crear un objeto
de motor a partir del URI de la base de datos. Solo necesita crear el motor una vez por
base de datos a la que se está conectando.

from sqlalchemy import create_engine

engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase')

engine = create_engine('mysql+mysqldb://scott:tiger@localhost/foo')

engine = create_engine('oracle://scott:[email protected]:1521/sidname')

engine = create_engine('mssql+pyodbc://mydsn')

# sqlite://<nohostname>/<path>
# where <path> is relative:
engine = create_engine('sqlite:///foo.db')

# or absolute, starting with a slash:


engine = create_engine('sqlite:////absolute/path/to/foo.db')

Para obtener más información, consulte los ejemplos de la documentación


de SQLAlchemy

Consultas avanzadas de SQLAlchemy 


Puede usar construcciones SQLAlchemy para describir su consulta.

Se usa sqlalchemy.text()para especificar parámetros de consulta de una manera neutral


en el backend

In [537]: import sqlalchemy as sa

In [538]: pd.read_sql(sa.text('SELECT * FROM data where Col_1=:col1'),


.....: engine, params={'col1': 'X'})
.....:
Out[538]:
index id Date Col_1 Col_2 Col_3
0 0 26 2010-10-18 00:00:00.000000 X 27.5 1

Si tiene una descripción SQLAlchemy de su base de datos, puede expresar dónde las
condiciones usan expresiones SQLAlchemy

In [539]: metadata = sa.MetaData()


In [540]: data_table = sa.Table('data', metadata,
.....: sa.Column('index', sa.Integer),
.....: sa.Column('Date', sa.DateTime),
.....: sa.Column('Col_1', sa.String),
.....: sa.Column('Col_2', sa.Float),
.....: sa.Column('Col_3', sa.Boolean),
.....: )
.....:

In [541]: pd.read_sql(sa.select([data_table]).where(data_table.c.Col_3 is True),


engine)
Out[541]:
Empty DataFrame
Columns: [index, Date, Col_1, Col_2, Col_3]
Index: []

Puede combinar expresiones SQLAlchemy con parámetros pasados


al read_sql()usosqlalchemy.bindparam()

In [542]: import datetime as dt

In [543]: expr = sa.select([data_table]).where(data_table.c.Date >


sa.bindparam('date'))

In [544]: pd.read_sql(expr, engine, params={'date': dt.datetime(2010, 10, 18)})


Out[544]:
index Date Col_1 Col_2 Col_3
0 1 2010-10-19 Y -12.50 False
1 2 2010-10-20 Z 5.73 True

Reserva de SQLite 
El uso de sqlite es compatible sin usar SQLAlchemy. Este modo requiere un adaptador de
base de datos Python que respete la API de Python DB .

Puede crear conexiones de esta manera:

import sqlite3
con = sqlite3.connect(':memory:')

Y luego emita las siguientes consultas:


data.to_sql('data', con)
pd.read_sql_query("SELECT * FROM data", con)

Google BigQuery 
Advertencia

A partir de 0.20.0, pandas ha dividido el soporte de Google BigQuery en un paquete


separado pandas-gbq. Puedes conseguirlo.pip install pandas-gbq
El pandas-gbqpaquete proporciona funcionalidad para leer / escribir desde Google
BigQuery.

pandas se integra con este paquete externo. si pandas-gbqestá instalado, puede usar los
métodos pandas pd.read_gbqy DataFrame.to_gbq, que llamará a las funciones respectivas
desde pandas-gbq.

La documentación completa se puede encontrar aquí .

Formato Stata 
Escribiendo en formato stata 
El método to_stata()escribirá un DataFrame en un archivo .dta. La versión de formato de
este archivo es siempre 115 (Stata 12).

In [545]: df = pd.DataFrame(np.random.randn(10, 2), columns=list('AB'))

In [546]: df.to_stata('stata.dta')

Los archivos de datos Stata tienen un soporte de tipo de datos limitado; sólo cadenas con


244 o menos caracteres, int8, int16, int32, float32 y float64se pueden almacenar
en .dtaarchivos. Además, Stata se reserva ciertos valores para representar los datos
faltantes. Exportar un valor no perdido que esté fuera del rango permitido en Stata para
un tipo de datos en particular volverá a escribir la variable al siguiente tamaño más
grande. Por ejemplo, los int8valores están restringidos para estar entre -127 y 100 en
Stata, por lo que las variables con valores superiores a 100 desencadenarán una
conversión a int16. nanLos valores en los tipos de datos de coma flotante se almacenan
como el tipo de datos faltantes básico ( .en Stata ).

Nota

No es posible exportar valores de datos faltantes para tipos de datos enteros.


El Stata escritor maneja con gracia otros tipos de datos,
incluyendo int64, bool, uint8, uint16, uint32echando a un tipo admitido más pequeña que
puede representar los datos. Por ejemplo, los datos con un tipo de uint8se
convertirán int8si todos los valores son inferiores a 100 (el límite superior para
los int8datos que no faltan en Stata ) o, si los valores están fuera de este rango, la variable
se convierte a int16.

Advertencia

La conversión de int64a float64puede resultar en una pérdida de precisión si


los int64valores son mayores que 2 ** 53.

Advertencia

StataWritery to_stata()solo admite cadenas de ancho fijo que contienen hasta 244


caracteres, una limitación impuesta por el formato de archivo de la versión 115
dta. Intentar escribir archivos Stata dta con cadenas de más de 244 caracteres plantea
a ValueError.

Lectura del formato Stata 


La función de nivel superior read_stataleerá un archivo dta y devolverá una DataFrameo
una StataReaderque puede usarse para leer el archivo de forma incremental.

In [547]: pd.read_stata('stata.dta')
Out[547]:
index A B
0 0 0.608228 1.064810
1 1 -0.780506 -2.736887
2 2 0.143539 1.170191
3 3 -1.573076 0.075792
4 4 -1.722223 -0.774650
5 5 0.803627 0.221665
6 6 0.584637 0.147264
7 7 1.057825 -0.284136
8 8 0.912395 1.552808
9 9 0.189376 -0.109830

Especificar un chunksizeproduce una StataReaderinstancia que se puede usar para


leer chunksizelíneas del archivo a la vez. El StataReader objeto se puede usar como un
iterador.

In [548]: reader = pd.read_stata('stata.dta', chunksize=3)

In [549]: for df in reader:


.....: print(df.shape)
.....:
(3, 3)
(3, 3)
(3, 3)
(1, 3)

Para un control más detallado, use iterator=Truey especifique chunksizecon cada llamada


a read().

In [550]: reader = pd.read_stata('stata.dta', iterator=True)

In [551]: chunk1 = reader.read(5)

In [552]: chunk2 = reader.read(5)

Actualmente indexse recupera como una columna.

El parámetro convert_categoricalsindica si las etiquetas de valor deben leerse y usarse


para crear una Categoricalvariable a partir de ellas. La función también puede recuperar
las etiquetas de valor value_labels, que read() deben llamarse antes de su uso.

El parámetro convert_missingindica si se deben preservar las representaciones de valores


faltantes en Stata. Si False(el valor predeterminado), los valores faltantes se representan
como np.nan. Si True, los valores faltantes se representan
usando StataMissingValueobjetos, y las columnas que contienen valores perdidos tendrán
un objecttipo de datos.

Nota

read_stata()y StataReaderadmite formatos .dta 113-115 (Stata 10-12), 117 (Stata 13) y


118 (Stata 14).

Nota

La configuración preserve_dtypes=Falsese elevará a los tipos de datos de pandas


estándar: int64para todos los tipos de enteros y float64para datos de punto flotante. Por
defecto, los tipos de datos Stata se conservan al importar.

Datos categóricos 
Categoricallos datos se pueden exportar a archivos de datos Stata como datos
etiquetados como valores. Los datos exportados consisten en los códigos de categoría
subyacentes como valores de datos enteros y las categorías como etiquetas de
valor. Stata no tiene un equivalente explícito a ay la Categoricalinformación sobre si la
variable está ordenada se pierde al exportar.
Advertencia

Stata solo admite etiquetas de valor de cadena, por lo que strse llama a las categorías al
exportar datos. La exportación de Categoricalvariables con categorías que no son
cadenas produce una advertencia y puede provocar una pérdida de información si
las strrepresentaciones de las categorías no son únicas.
Los datos etiquetados se pueden importar de manera similar desde los archivos de datos
de Stata como Categorical variables utilizando el argumento de la palabra
clave convert_categoricals( Truepor defecto). El argumento de la palabra
clave order_categoricals( Truepor defecto) determina si
las Categoricalvariables importadas están ordenadas.

Nota

Al importar datos categóricos, los valores de las variables en el archivo de datos Stata no


se conservan ya que las Categoricalvariables siempre usan tipos de datos enteros entre -
1y n-1dónde nestá el número de categorías. Si se requieren los valores originales en
el archivo de datos Stata , estos se pueden importar mediante la
configuración convert_categoricals=False, que importará los datos originales (pero no las
etiquetas variables). Los valores originales pueden coincidir con los datos categóricos
importados, ya que existe un mapeo simple entre los valores de datos Stata originales y
los códigos de categoría de las variables categóricas importadas: a los valores faltantes se
les asigna un código -1y se asigna el valor original más pequeño 0, el segundo asignado 1y
así sucesivamente hasta que se asigne el mayor valor original al código n-1.

Nota

Stata admite series parcialmente etiquetadas. Estas series tienen etiquetas de valor para


algunos pero no todos los valores de datos. La importación de una serie parcialmente
etiquetada producirá una Categoricalcon categorías de cadena para los valores que están
etiquetados y categorías numéricas para valores sin etiqueta.

Formatos SAS 
La función de nivel superior read_sas()puede leer (pero no escribir) SAS xport (.xpt) y
(ya v0.18.0 ) SAS7BDAT archivos de formato (.sas7bdat).

Los archivos SAS solo contienen dos tipos de valores: texto ASCII y valores de coma
flotante (generalmente 8 bytes pero a veces truncados). Para los archivos xport, no hay
conversión automática de tipo a enteros, fechas o categorías. Para los archivos
SAS7BDAT, los códigos de formato pueden permitir que las variables de fecha se
conviertan automáticamente en fechas. Por defecto, todo el archivo se lee y se devuelve
como a DataFrame.

Especifique ao chunksizeuse iterator=Truepara obtener objetos de lector


( XportReadero SAS7BDATReader) para leer el archivo de forma incremental. Los objetos
lectores también tienen atributos que contienen información adicional sobre el archivo y
sus variables.

Lea un archivo SAS7BDAT:

df = pd.read_sas('sas_data.sas7bdat')

Obtenga un iterador y lea un archivo XPORT de 100,000 líneas a la vez:

def do_something(chunk):
pass

rdr = pd.read_sas('sas_xport.xpt', chunk=100000)


for chunk in rdr:
do_something(chunk)

La especificación para el formato de archivo xport está disponible en el sitio web de SAS.

No hay documentación oficial disponible para el formato SAS7BDAT.

Formatos SPSS 
Nuevo en la versión 0.25.0.

La función de nivel superior read_spss()puede leer (pero no escribir) archivos de


formato SPSS sav (.sav) y zsav (.zsav).

Los archivos SPSS contienen nombres de columna. Por defecto, se lee todo el archivo, las
columnas categóricas se convierten pd.Categoricaly DataFramese devuelve a con todas
las columnas.

Especifique el usecolsparámetro para obtener un subconjunto de


columnas. Especifique convert_categoricals=False para evitar convertir columnas
categóricas en pd.Categorical.

Leer un archivo SPSS:

df = pd.read_spss('spss_data.sav')

Extraiga un subconjunto de columnas contenidas en usecolsun archivo SPSS y evite


convertir columnas categóricas en pd.Categorical:

df = pd.read_spss('spss_data.sav', usecols=['foo', 'bar'],


convert_categoricals=False)

Más información sobre el formato de archivo sav y zsav está disponible aquí .

Otros formatos de archivo 


pandas solo admite IO con un conjunto limitado de formatos de archivo que se asignan
limpiamente a su modelo de datos tabulares. Para leer y escribir otros formatos de archivo
en y desde pandas, recomendamos estos paquetes de la comunidad en general.

netCDF 
xarray proporciona estructuras de datos inspiradas en los pandas DataFramepara trabajar
con conjuntos de datos multidimensionales, con un enfoque en el formato de archivo
netCDF y una fácil conversión hacia y desde los pandas.

Consideraciones de rendimiento 
Esta es una comparación informal de varios métodos IO, usando pandas 0.24.2. Los
tiempos dependen de la máquina y se deben ignorar las pequeñas diferencias.

In [1]: sz = 1000000
In [2]: df = pd.DataFrame({'A': np.random.randn(sz), 'B': [1] * sz})

In [3]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000000 entries, 0 to 999999
Data columns (total 2 columns):
A 1000000 non-null float64
B 1000000 non-null int64
dtypes: float64(1), int64(1)
memory usage: 15.3 MB

Dado el siguiente conjunto de pruebas:

import numpy as np

import os

sz = 1000000
df = pd.DataFrame({'A': np.random.randn(sz), 'B': [1] * sz})
sz = 1000000
np.random.seed(42)
df = pd.DataFrame({'A': np.random.randn(sz), 'B': [1] * sz})

def test_sql_write(df):
if os.path.exists('test.sql'):
os.remove('test.sql')
sql_db = sqlite3.connect('test.sql')
df.to_sql(name='test_table', con=sql_db)
sql_db.close()

def test_sql_read():
sql_db = sqlite3.connect('test.sql')
pd.read_sql_query("select * from test_table", sql_db)
sql_db.close()

def test_hdf_fixed_write(df):
df.to_hdf('test_fixed.hdf', 'test', mode='w')

def test_hdf_fixed_read():
pd.read_hdf('test_fixed.hdf', 'test')

def test_hdf_fixed_write_compress(df):
df.to_hdf('test_fixed_compress.hdf', 'test', mode='w', complib='blosc')

def test_hdf_fixed_read_compress():
pd.read_hdf('test_fixed_compress.hdf', 'test')

def test_hdf_table_write(df):
df.to_hdf('test_table.hdf', 'test', mode='w', format='table')

def test_hdf_table_read():
pd.read_hdf('test_table.hdf', 'test')

def test_hdf_table_write_compress(df):
df.to_hdf('test_table_compress.hdf', 'test', mode='w',
complib='blosc', format='table')

def test_hdf_table_read_compress():
pd.read_hdf('test_table_compress.hdf', 'test')

def test_csv_write(df):
df.to_csv('test.csv', mode='w')

def test_csv_read():
pd.read_csv('test.csv', index_col=0)

def test_feather_write(df):
df.to_feather('test.feather')

def test_feather_read():
pd.read_feather('test.feather')

def test_pickle_write(df):
df.to_pickle('test.pkl')

def test_pickle_read():
pd.read_pickle('test.pkl')

def test_pickle_write_compress(df):
df.to_pickle('test.pkl.compress', compression='xz')

def test_pickle_read_compress():
pd.read_pickle('test.pkl.compress', compression='xz')

def test_parquet_write(df):
df.to_parquet('test.parquet')

def test_parquet_read():
pd.read_parquet('test.parquet')

Al escribir, las tres funciones principales en términos de velocidad


son test_feather_write, test_hdf_fixed_writey test_hdf_fixed_write_compress.

In [4]: %timeit test_sql_write(df)


3.29 s ± 43.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [5]: %timeit test_hdf_fixed_write(df)


19.4 ms ± 560 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [6]: %timeit test_hdf_fixed_write_compress(df)


19.6 ms ± 308 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [7]: %timeit test_hdf_table_write(df)


449 ms ± 5.61 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [8]: %timeit test_hdf_table_write_compress(df)


448 ms ± 11.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [9]: %timeit test_csv_write(df)


3.66 s ± 26.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [10]: %timeit test_feather_write(df)


9.75 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [11]: %timeit test_pickle_write(df)


30.1 ms ± 229 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [12]: %timeit test_pickle_write_compress(df)


4.29 s ± 15.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [13]: %timeit test_parquet_write(df)


67.6 ms ± 706 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Al leer, los tres primeros son test_feather_read, test_pickle_ready test_hdf_fixed_read.

In [14]: %timeit test_sql_read()


1.77 s ± 17.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [15]: %timeit test_hdf_fixed_read()


19.4 ms ± 436 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [16]: %timeit test_hdf_fixed_read_compress()


19.5 ms ± 222 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [17]: %timeit test_hdf_table_read()


38.6 ms ± 857 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [18]: %timeit test_hdf_table_read_compress()


38.8 ms ± 1.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [19]: %timeit test_csv_read()


452 ms ± 9.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [20]: %timeit test_feather_read()


12.4 ms ± 99.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [21]: %timeit test_pickle_read()


18.4 ms ± 191 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [22]: %timeit test_pickle_read_compress()


915 ms ± 7.48 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [23]: %timeit test_parquet_read()


24.4 ms ± 146 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Para este caso de prueba test.pkl.compress, test.parquety test.feathertomó el menor
espacio en el disco. Espacio en disco (en bytes)

29519500 Oct 10 06:45 test.csv


16000248 Oct 10 06:45 test.feather
8281983 Oct 10 06:49 test.parquet
16000857 Oct 10 06:47 test.pkl
7552144 Oct 10 06:48 test.pkl.compress
34816000 Oct 10 06:42 test.sql
24009288 Oct 10 06:43 test_fixed.hdf
24009288 Oct 10 06:43 test_fixed_compress.hdf
24458940 Oct 10 06:44 test_table.hdf
24458940 Oct 10 06:44 test_table_compress.hdf

También podría gustarte