read_csv - read text pandas python
Mejore el rendimiento de escritura de tablas pandas(PyTables?) HDF5 (2)
Esa es una discusión interesante. Creo que Peter está obteniendo un desempeño impresionante para el formato Fixed porque el formato escribe en una sola toma y también que tiene una SSD realmente buena (puede escribir a más de 450 MB / s).
Agregar a la tabla es una operación más compleja (el conjunto de datos tiene que ser ampliado, y los nuevos registros deben ser verificados para que podamos asegurarnos de que sigan el esquema de la tabla). Esta es la razón por la cual las filas añadidas en las tablas generalmente son más lentas (pero aún así, Jeff obtiene ~ 70 MB / s, lo cual es bastante bueno). Que Jeff esté obteniendo más velocidad que Peter probablemente se deba al hecho de que tiene un mejor procesador.
Finalmente, la indexación en PyTables usa un solo procesador, sí, y eso normalmente es una operación costosa, por lo que realmente debería deshabilitarla si no va a consultar datos en el disco.
He estado usando pandas para investigar ahora durante aproximadamente dos meses con gran efecto. Con una gran cantidad de datasets de eventos de rastreo de tamaño mediano, pandas + PyTables (la interfaz HDF5) hace un trabajo tremendo al permitirme procesar datos heterogéneos usando todas las herramientas de Python que conozco y amo.
En general, utilizo el formato Fixed (anteriormente "Storer") en PyTables, ya que mi flujo de trabajo es write-once, read-many, y muchos de mis datasets tienen un tamaño tal que puedo cargar 50-100 de ellos en la memoria a tiempo sin inconvenientes serios (NB: hago gran parte de mi trabajo en máquinas de clase de servidor Opteron con 128 GB de memoria de sistema).
Sin embargo, para grandes conjuntos de datos (500MB y más), me gustaría poder utilizar las capacidades de consulta y acceso aleatorio más escalables del formato de "Tablas" de PyTables, para que pueda realizar mis consultas sin memoria y luego cargue el conjunto de resultados mucho más pequeño en la memoria para su procesamiento. El gran obstáculo aquí, sin embargo, es el rendimiento de escritura. Sí, como dije, mi flujo de trabajo es de escritura única, lectura de muchos, pero los tiempos relativos aún son inaceptables.
Como ejemplo, recientemente ejecuté una gran factorización de Cholesky que tomó 3 minutos, 8 segundos (188 segundos) en mi máquina de 48 núcleos. Esto generó un archivo de rastreo de ~ 2.2 GB: el rastreo se genera en paralelo con el programa, por lo que no hay un "tiempo de creación de seguimiento" adicional.
La conversión inicial de mi archivo de rastreo binario en el formato pandas / PyTables toma una buena cantidad de tiempo, pero en gran parte porque el formato binario está deliberadamente fuera de servicio para reducir el impacto en el rendimiento del propio generador de seguimiento. Esto también es irrelevante para la pérdida de rendimiento al pasar del formato Storer al formato Table.
Mis pruebas se ejecutaron inicialmente con pandas 0.12, numpy 1.7.1, PyTables 2.4.0 y numexpr 0.20.1. Mi máquina de núcleo 48 funciona a 2.8 GHz por núcleo, y estoy escribiendo en un sistema de archivos ext3 que probablemente (pero no sin duda) en una SSD.
Puedo escribir el conjunto de datos completo en un archivo HDF5 en formato Storer (tamaño de archivo resultante: 3,3 GB) en 7,1 segundos. El mismo conjunto de datos, escrito en el formato de tabla (el tamaño del archivo resultante también es de 3,3 GB), tarda 178,7 segundos en escribirse.
El código es el siguiente:
with Timer() as t:
store = pd.HDFStore(''test_storer.h5'', ''w'')
store.put(''events'', events_dataset, table=False, append=False)
print(''Fixed format write took '' + str(t.interval))
with Timer() as t:
store = pd.HDFStore(''test_table.h5'', ''w'')
store.put(''events'', events_dataset, table=True, append=False)
print(''Table format write took '' + str(t.interval))
y la salida es simplemente
Fixed format write took 7.1
Table format write took 178.7
Mi conjunto de datos tiene 28,880,943 filas, y las columnas son tipos de datos básicos:
node_id int64
thread_id int64
handle_id int64
type int64
begin int64
end int64
duration int64
flags int64
unique_id int64
id int64
DSTL_LS_FULL float64
L2_DMISS float64
L3_MISS float64
kernel_type float64
dtype: object
... así que no creo que deba haber problemas específicos de datos con la velocidad de escritura.
También intenté agregar compresión BLOSC, para descartar cualquier problema de E / S extraño que pueda afectar un escenario u otro, pero la compresión parece disminuir el rendimiento de ambos por igual.
Ahora, me doy cuenta de que la documentación de los pandas dice que el formato Storer ofrece escrituras significativamente más rápidas y lecturas ligeramente más rápidas. (Experimento las lecturas más rápidas, ya que una lectura del formato Storer parece tardar unos 2,5 segundos, mientras que una lectura del formato de tabla tarda unos 10 segundos.) Pero realmente parece excesivo que la escritura del formato de tabla tome 25 veces más siempre y cuando el formato Storer escriba.
¿Puede alguna de las personas involucradas con PyTables o pandas explicar las razones arquitectónicas (o de otro tipo) por las cuales escribir en el formato consultable (que claramente requiere muy pocos datos adicionales) debería tomar un orden de magnitud más prolongado? ¿Y hay alguna esperanza para mejorar esto en el futuro? Me encantaría contribuir a un proyecto u otro, ya que mi campo es la informática de alto rendimiento y veo un caso de uso significativo para ambos proyectos en este campo ... pero sería útil obtener algunas aclaraciones sobre los problemas involucrados primero, y / o algunos consejos sobre cómo acelerar las cosas de aquellos que saben cómo se construye el sistema.
EDITAR:
Ejecutar las pruebas anteriores con% prun en IPython ofrece la siguiente salida de perfil (algo reducida para la legibilidad) para el formato Storer / Fixed:
%prun -l 20 profile.events.to_hdf(''test.h5'', ''events'', table=False, append=False)
3223 function calls (3222 primitive calls) in 7.385 seconds
Ordered by: internal time
List reduced from 208 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
6 7.127 1.188 7.128 1.188 {method ''_createArray'' of ''tables.hdf5Extension.Array'' objects}
1 0.242 0.242 0.242 0.242 {method ''_closeFile'' of ''tables.hdf5Extension.File'' objects}
1 0.003 0.003 0.003 0.003 {method ''_g_new'' of ''tables.hdf5Extension.File'' objects}
46 0.001 0.000 0.001 0.000 {method ''reduce'' of ''numpy.ufunc'' objects}
y lo siguiente para el formato de tablas:
%prun -l 40 profile.events.to_hdf(''test.h5'', ''events'', table=True, append=False, chunksize=1000000)
499082 function calls (499040 primitive calls) in 188.981 seconds
Ordered by: internal time
List reduced from 526 to 40 due to restriction <40>
ncalls tottime percall cumtime percall filename:lineno(function)
29 92.018 3.173 92.018 3.173 {pandas.lib.create_hdf_rows_2d}
640 20.987 0.033 20.987 0.033 {method ''_append'' of ''tables.hdf5Extension.Array'' objects}
29 19.256 0.664 19.256 0.664 {method ''_append_records'' of ''tables.tableExtension.Table'' objects}
406 19.182 0.047 19.182 0.047 {method ''_g_writeSlice'' of ''tables.hdf5Extension.Array'' objects}
14244 10.646 0.001 10.646 0.001 {method ''_g_readSlice'' of ''tables.hdf5Extension.Array'' objects}
472 10.359 0.022 10.359 0.022 {method ''copy'' of ''numpy.ndarray'' objects}
80 3.409 0.043 3.409 0.043 {tables.indexesExtension.keysort}
2 3.023 1.512 3.023 1.512 common.py:134(_isnull_ndarraylike)
41 2.489 0.061 2.533 0.062 {method ''_fillCol'' of ''tables.tableExtension.Row'' objects}
87 2.401 0.028 2.401 0.028 {method ''astype'' of ''numpy.ndarray'' objects}
30 1.880 0.063 1.880 0.063 {method ''_g_flush'' of ''tables.hdf5Extension.Leaf'' objects}
282 0.824 0.003 0.824 0.003 {method ''reduce'' of ''numpy.ufunc'' objects}
41 0.537 0.013 0.668 0.016 index.py:607(final_idx32)
14490 0.385 0.000 0.712 0.000 array.py:342(_interpret_indexing)
39 0.279 0.007 19.635 0.503 index.py:1219(reorder_slice)
2 0.256 0.128 10.063 5.031 index.py:1099(get_neworder)
1 0.090 0.090 119.392 119.392 pytables.py:3016(write_data)
57842 0.087 0.000 0.087 0.000 {numpy.core.multiarray.empty}
28570 0.062 0.000 0.107 0.000 utils.py:42(is_idx)
14164 0.062 0.000 7.181 0.001 array.py:711(_readSlice)
EDICION 2:
Corriendo de nuevo con una copia preliminar de pandas 0.13 (retirada el 20 de noviembre de 2013 a alrededor de las 11:00 EST), los tiempos de escritura para el formato de tablas mejoran significativamente pero aún no se pueden comparar "razonablemente" con las velocidades de escritura del Storer / Fixed formato.
%prun -l 40 profile.events.to_hdf(''test.h5'', ''events'', table=True, append=False, chunksize=1000000)
499748 function calls (499720 primitive calls) in 117.187 seconds
Ordered by: internal time
List reduced from 539 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
640 22.010 0.034 22.010 0.034 {method ''_append'' of ''tables.hdf5Extension.Array'' objects}
29 20.782 0.717 20.782 0.717 {method ''_append_records'' of ''tables.tableExtension.Table'' objects}
406 19.248 0.047 19.248 0.047 {method ''_g_writeSlice'' of ''tables.hdf5Extension.Array'' objects}
14244 10.685 0.001 10.685 0.001 {method ''_g_readSlice'' of ''tables.hdf5Extension.Array'' objects}
472 10.439 0.022 10.439 0.022 {method ''copy'' of ''numpy.ndarray'' objects}
30 7.356 0.245 7.356 0.245 {method ''_g_flush'' of ''tables.hdf5Extension.Leaf'' objects}
29 7.161 0.247 37.609 1.297 pytables.py:3498(write_data_chunk)
2 3.888 1.944 3.888 1.944 common.py:197(_isnull_ndarraylike)
80 3.581 0.045 3.581 0.045 {tables.indexesExtension.keysort}
41 3.248 0.079 3.294 0.080 {method ''_fillCol'' of ''tables.tableExtension.Row'' objects}
34 2.744 0.081 2.744 0.081 {method ''ravel'' of ''numpy.ndarray'' objects}
115 2.591 0.023 2.591 0.023 {method ''astype'' of ''numpy.ndarray'' objects}
270 0.875 0.003 0.875 0.003 {method ''reduce'' of ''numpy.ufunc'' objects}
41 0.560 0.014 0.732 0.018 index.py:607(final_idx32)
14490 0.387 0.000 0.712 0.000 array.py:342(_interpret_indexing)
39 0.303 0.008 19.617 0.503 index.py:1219(reorder_slice)
2 0.288 0.144 10.299 5.149 index.py:1099(get_neworder)
57871 0.087 0.000 0.087 0.000 {numpy.core.multiarray.empty}
1 0.084 0.084 45.266 45.266 pytables.py:3424(write_data)
1 0.080 0.080 55.542 55.542 pytables.py:3385(write)
Mientras ejecutaba estas pruebas me di cuenta de que hay largos períodos en los que la escritura parece "pausar" (el archivo en el disco no está creciendo activamente) y, sin embargo, también hay un bajo uso de la CPU durante algunos de estos períodos.
Empiezo a sospechar que algunas limitaciones conocidas de ext3 pueden interactuar mal con pandas o PyTables. Ext3 y otros sistemas de archivos no basados en extensiones a veces tienen dificultades para desvincular archivos de gran tamaño rápidamente, y un rendimiento similar del sistema (bajo uso de CPU, pero largos tiempos de espera) es aparente incluso durante una simple "rm" de un archivo de 1GB, por ejemplo.
Para aclarar, en cada caso de prueba, me aseguré de eliminar el archivo existente, en su caso, antes de comenzar la prueba, para no incurrir en ninguna multa de eliminación / sobrescritura de archivos ext3.
Sin embargo, al volver a ejecutar esta prueba con índice = Ninguno, el rendimiento mejora drásticamente (~ 50 s frente a los ~ 120 al indexar). Por lo tanto, parece que este proceso continúa vinculado a la CPU (mi sistema tiene CPUs AMD Opteron Istanbul relativamente antiguas que funcionan a 2.8 GHz, aunque también tiene 8 zócalos con 6 CPU centrales en cada uno, todos menos uno de los cuales, Por supuesto, permanezca inactivo durante la escritura), o que hay algún conflicto entre la forma en que PyTables o pandas intenta manipular / leer / analizar el archivo cuando ya está parcial o totalmente en el sistema de archivos que causa un comportamiento patológicamente malo de E / S cuando la indexación es ocurriendo.
EDIT 3:
Las pruebas sugeridas por @ Jeff en un conjunto de datos más pequeño (1,3 GB en el disco), después de actualizar PyTables de 2.4 a 3.0.0, me han traído aquí:
In [7]: %timeit f(df)
1 loops, best of 3: 3.7 s per loop
In [8]: %timeit f2(df) # where chunksize= 2 000 000
1 loops, best of 3: 13.8 s per loop
In [9]: %timeit f3(df) # where chunksize= 2 000 000
1 loops, best of 3: 43.4 s per loop
De hecho, mi rendimiento parece superarlo en todos los escenarios, excepto cuando la indexación está activada (valor predeterminado). Sin embargo, la indexación todavía parece ser un asesino, y si la forma en que estoy interpretando el resultado de top
y ls
es correcta, quedan periodos de tiempo en los que no hay procesamiento significativo ni escritura de archivos (es decir, , El uso de CPU para el proceso de Python está cerca de 0, y el tamaño del archivo permanece constante). Solo puedo suponer que estas son lecturas de archivos. No entiendo por qué las lecturas de archivos causarían ralentizaciones, ya que puedo cargar confiablemente un archivo entero de 3+ GB de este disco en la memoria en menos de 3 segundos. Si no son lecturas de archivo, entonces, ¿qué está esperando el sistema? (Nadie más está conectado a la máquina, y no hay otra actividad del sistema de archivos).
En este punto, con las versiones mejoradas de los módulos de python relevantes, el rendimiento de mi conjunto de datos original se reduce a las siguientes figuras. De especial interés es el tiempo del sistema, que supongo que es al menos un límite superior en el tiempo dedicado a realizar IO, y el tiempo de Muro, que tal vez explique estos periodos misteriosos sin actividad de escritura / sin CPU.
In [28]: %time f(profile.events)
CPU times: user 0 ns, sys: 7.16 s, total: 7.16 s
Wall time: 7.51 s
In [29]: %time f2(profile.events)
CPU times: user 18.7 s, sys: 14 s, total: 32.7 s
Wall time: 47.2 s
In [31]: %time f3(profile.events)
CPU times: user 1min 18s, sys: 14.4 s, total: 1min 32s
Wall time: 2min 5s
Sin embargo, parece que la indexación causa una desaceleración significativa para mi caso de uso. Quizás debería intentar limitar los campos indexados en lugar de simplemente realizar el caso predeterminado (que bien puede estar indexando en todos los campos en el DataFrame). No estoy seguro de cómo es probable que esto afecte los tiempos de consulta, especialmente en los casos en que una consulta selecciona en función de un campo no indexado.
Según la solicitud de Jeff, un ptdump del archivo resultante.
ptdump -av test.h5
/ (RootGroup) ''''
/._v_attrs (AttributeSet), 4 attributes:
[CLASS := ''GROUP'',
PYTABLES_FORMAT_VERSION := ''2.1'',
TITLE := '''',
VERSION := ''1.0'']
/df (Group) ''''
/df._v_attrs (AttributeSet), 14 attributes:
[CLASS := ''GROUP'',
TITLE := '''',
VERSION := ''1.0'',
data_columns := [],
encoding := None,
index_cols := [(0, ''index'')],
info := {1: {''type'': ''Index'', ''names'': [None]}, ''index'': {}},
levels := 1,
nan_rep := ''nan'',
non_index_axes :=
[(1, [''node_id'', ''thread_id'', ''handle_id'', ''type'', ''begin'', ''end'', ''duration'', ''flags'', ''unique_id'', ''id'', ''DSTL_LS_FULL'', ''L2_DMISS'', ''L3_MISS'', ''kernel_type''])],
pandas_type := ''frame_table'',
pandas_version := ''0.10.1'',
table_type := ''appendable_frame'',
values_cols := [''values_block_0'', ''values_block_1'']]
/df/table (Table(28880943,)) ''''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": Int64Col(shape=(10,), dflt=0, pos=1),
"values_block_1": Float64Col(shape=(4,), dflt=0.0, pos=2)}
byteorder := ''little''
chunkshape := (4369,)
autoindex := True
colindexes := {
"index": Index(6, medium, shuffle, zlib(1)).is_csi=False}
/df/table._v_attrs (AttributeSet), 15 attributes:
[CLASS := ''TABLE'',
FIELD_0_FILL := 0,
FIELD_0_NAME := ''index'',
FIELD_1_FILL := 0,
FIELD_1_NAME := ''values_block_0'',
FIELD_2_FILL := 0.0,
FIELD_2_NAME := ''values_block_1'',
NROWS := 28880943,
TITLE := '''',
VERSION := ''2.7'',
index_kind := ''integer'',
values_block_0_dtype := ''int64'',
values_block_0_kind := [''node_id'', ''thread_id'', ''handle_id'', ''type'', ''begin'', ''end'', ''duration'', ''flags'', ''unique_id'', ''id''],
values_block_1_dtype := ''float64'',
values_block_1_kind := [''DSTL_LS_FULL'', ''L2_DMISS'', ''L3_MISS'', ''kernel_type'']]
y otro% prun con los módulos actualizados y el conjunto de datos completo:
%prun -l 25 %time f3(profile.events)
CPU times: user 1min 14s, sys: 16.2 s, total: 1min 30s
Wall time: 1min 48s
542678 function calls (542650 primitive calls) in 108.678 seconds
Ordered by: internal time
List reduced from 629 to 25 due to restriction <25>
ncalls tottime percall cumtime percall filename:lineno(function)
640 23.633 0.037 23.633 0.037 {method ''_append'' of ''tables.hdf5extension.Array'' objects}
15 20.852 1.390 20.852 1.390 {method ''_append_records'' of ''tables.tableextension.Table'' objects}
406 19.584 0.048 19.584 0.048 {method ''_g_write_slice'' of ''tables.hdf5extension.Array'' objects}
14244 10.591 0.001 10.591 0.001 {method ''_g_read_slice'' of ''tables.hdf5extension.Array'' objects}
458 9.693 0.021 9.693 0.021 {method ''copy'' of ''numpy.ndarray'' objects}
15 6.350 0.423 30.989 2.066 pytables.py:3498(write_data_chunk)
80 3.496 0.044 3.496 0.044 {tables.indexesextension.keysort}
41 3.335 0.081 3.376 0.082 {method ''_fill_col'' of ''tables.tableextension.Row'' objects}
20 2.551 0.128 2.551 0.128 {method ''ravel'' of ''numpy.ndarray'' objects}
101 2.449 0.024 2.449 0.024 {method ''astype'' of ''numpy.ndarray'' objects}
16 1.789 0.112 1.789 0.112 {method ''_g_flush'' of ''tables.hdf5extension.Leaf'' objects}
2 1.728 0.864 1.728 0.864 common.py:197(_isnull_ndarraylike)
41 0.586 0.014 0.842 0.021 index.py:637(final_idx32)
14490 0.292 0.000 0.616 0.000 array.py:368(_interpret_indexing)
2 0.283 0.142 10.267 5.134 index.py:1158(get_neworder)
274 0.251 0.001 0.251 0.001 {method ''reduce'' of ''numpy.ufunc'' objects}
39 0.174 0.004 19.373 0.497 index.py:1280(reorder_slice)
57857 0.085 0.000 0.085 0.000 {numpy.core.multiarray.empty}
1 0.083 0.083 35.657 35.657 pytables.py:3424(write_data)
1 0.065 0.065 45.338 45.338 pytables.py:3385(write)
14164 0.065 0.000 7.831 0.001 array.py:615(__getitem__)
28570 0.062 0.000 0.108 0.000 utils.py:47(is_idx)
47 0.055 0.001 0.055 0.001 {numpy.core.multiarray.arange}
28570 0.050 0.000 0.090 0.000 leaf.py:397(_process_range)
87797 0.048 0.000 0.048 0.000 {isinstance}
Aquí hay una comparación similar que acabo de hacer. Es aproximadamente 1/3 de las filas de datos 10M. El tamaño final es de aproximadamente 1.3 GB
Defino 3 funciones de tiempo:
Pruebe el formato fijo (llamado Storer en 0.12). Esto escribe en un formato de matriz PyTables
def f(df):
store = pd.HDFStore(''test.h5'',''w'')
store[''df''] = df
store.close()
Escriba en el formato de tabla, utilizando el formato de tabla PyTables. No crees un índice.
def f2(df):
store = pd.HDFStore(''test.h5'',''w'')
store.append(''df'',df,index=False)
store.close()
Igual que f2, pero crea un índice (que normalmente se hace)
def f3(df):
store = pd.HDFStore(''test.h5'',''w'')
store.append(''df'',df)
store.close()
Crea el marco
In [25]: df = concat([DataFrame(np.random.randn(10000000,10)),DataFrame(np.random.randint(0,10,size=50000000).reshape(10000000,5))],axis=1)
In [26]: df
Out[26]:
<class ''pandas.core.frame.DataFrame''>
Int64Index: 10000000 entries, 0 to 9999999
Columns: 15 entries, 0 to 4
dtypes: float64(10), int64(5)
v0.12.0
In [27]: %timeit f(df)
1 loops, best of 3: 14.7 s per loop
In [28]: %timeit f2(df)
1 loops, best of 3: 32 s per loop
In [29]: %timeit f3(df)
1 loops, best of 3: 40.1 s per loop
master/v0.13.0
In [5]: %timeit f(df)
1 loops, best of 3: 12.9 s per loop
In [6]: %timeit f2(df)
1 loops, best of 3: 17.5 s per loop
In [7]: %timeit f3(df)
1 loops, best of 3: 24.3 s per loop
Tiempos Se ejecuta con el mismo archivo proporcionado por el OP (el enlace está debajo)
In [4]: df = pd.read_hdf(''test.h5'',''df'')
In [5]: df
Out[5]:
<class ''pandas.core.frame.DataFrame''>
Int64Index: 28880943 entries, 0 to 28880942
Columns: 14 entries, node_id to kernel_type
dtypes: float64(4), int64(10)
Como f1, formato fijo
In [6]: %timeit df.to_hdf(''test.hdf'',''df'',mode=''w'')
1 loops, best of 3: 36.2 s per loop
Como f2, formato de tabla, sin índice
In [7]: %timeit df.to_hdf(''test.hdf'',''df'',mode=''w'',format=''table'',index=False)
1 loops, best of 3: 45 s per loop
In [8]: %timeit df.to_hdf(''test.hdf'',''df'',mode=''w'',format=''table'',index=False,chunksize=2000000)
1 loops, best of 3: 44.5 s per loop
Como f3, formato de tabla con índice
In [9]: %timeit df.to_hdf(''test.hdf'',''df'',mode=''w'',format=''table'',chunksize=2000000)
1 loops, best of 3: 1min 36s per loop
Como f3, formato de tabla con índice, comprimido con blosc
In [10]: %timeit df.to_hdf(''test.hdf'',''df'',mode=''w'',format=''table'',chunksize=2000000,complib=''blosc'')
1 loops, best of 3: 46.5 s per loop
In [11]: %timeit pd.read_hdf(''test.hdf'',''df'')
1 loops, best of 3: 10.8 s per loop
Mostrar el archivo original (test.h5, y comprimido, test.hdf)
In [13]: !ls -ltr test.h*
-rw-r--r-- 1 jreback users 3471518282 Nov 20 18:20 test.h5
-rw-rw-r-- 1 jreback users 649327780 Nov 20 21:17 test.hdf
Varios puntos para tener en cuenta.
No crear un índice puede hacer una diferencia no trivial en el tiempo. También creo que si tiene un índice basado en cadenas, puede empeorar sustancialmente el tiempo de escritura. Dicho eso, siempre quieres crear un índice para hacer la recuperación muy rápido.
No incluyó lo que es su índice, ni si está ordenado (aunque creo que esto hace una pequeña diferencia).
la penalización de escritura en mis ejemplos es aproximadamente 2x (aunque he visto que es algo mayor cuando INCLUYE el tiempo de índice). Por lo tanto, sus 7s (1/2 de mi tiempo), por 3 veces el número que estoy escribiendo es bastante sospechoso. Estoy usando una matriz de discos razonablemente rápida. Si estaba usando un disco basado en flash, entonces esto es posible.
master / v0.13.0 (lanzamiento muy pronto), mejora sustancialmente los tiempos de escritura en tablas.
puede intentar establecer el parámetro de
chunksize
grande en un número mayor al escribir los datos (su valor predeterminado es 100000). El propósito del número "relativamente bajo" es tener un uso de memoria constante. (por ejemplo, si es más grande usará más memoria, en teoría debería escribir más rápido).Las tablas ofrecen 2 ventajas sobre el formato fijo: 1) recuperación de consultas, y 2) appendability. Tampoco se aprovecha la lectura de toda la tabla, por lo que si SOLO desea leer toda la tabla, se recomienda el formato Fijo. (En mi experiencia, la flexibilidad de las tablas pesa mucho más que la penalización de escritura, pero YMMV)
La conclusión es repetir los tiempos (use ipython ya que ejecutará múltiples pruebas). Si puedes reproducir tus resultados, entonces pls publica un% prun y lo echaré un vistazo.
Actualizar:
así que la forma recomendada para una tabla de este tamaño es comprimir con blosc y usar pandas master / 0.13.0 junto con PyTables 3.0.0