2012-02-02 10 views
15

¿Es posible inicializar una repetición de numpy que contendrá cadenas, sin conocer la longitud de las cadenas de antemano?cadenas de recarray numpy de longitud variable

Como (artificial) ejemplo:

mydf = np.empty((numrows,), dtype=[ ('file_name','STRING'), ('file_size_MB',float) ]) 

El problema es que estoy construyendo mi recArray antes de rellenar con la información, y no necesariamente conoce la longitud máxima de file_name de antemano .

Todos mis intentos resultan en el campo de cadena que se está truncado:

>>> mydf = np.empty((2,), dtype=[('file_name',str),('file_size_mb',float)]) 
>>> mydf['file_name'][0]='foobarasdf.tif' 
>>> mydf['file_name'][1]='arghtidlsarbda.jpg' 
>>> mydf 
array([('', 6.9164002347457e-310), ('', 9.9413127e-317)], 
     dtype=[('file_name', 'S'), ('file_size_mb', '<f8')]) 
>>> mydf['file_name'] 
array(['f', 'a'], 
     dtype='|S1') 

(Dicho sea de paso, ¿por qué mydf['file_name'] espectáculo 'f' y 'a', mientras que mydf espectáculos '' y ''?)

del mismo modo, si inicializar con el tipo (por ejemplo) para |S10file_name entonces las cosas se ponen truncada largamente 10.

La única pregunta similar que pude encontrar es this one, pero esta calcu indica la longitud de cadena apropiada a priori y por lo tanto no es exactamente igual a la mía (como no sé nada de antemano).

¿Hay alguna otra alternativa que no sea la inicialización de file_name con (por ejemplo) |S9999999999999 (es decir, algún límite superior ridículo)?

+0

esta es una buena pregunta. longitud de 0 cuerdas en recarrays solo me hizo arrancarme el pelo durante media hora! – Christoph

Respuesta

24

En lugar de usar el tipo STRING, siempre se puede usar object como dtype. Eso permitirá que cualquier objeto se asigne a un elemento de matriz, incluidas las cadenas de longitud variable de Python. Por ejemplo:

>>> import numpy as np 
>>> mydf = np.empty((2,), dtype=[('file_name',object),('file_size_mb',float)]) 
>>> mydf['file_name'][0]='foobarasdf.tif' 
>>> mydf['file_name'][1]='arghtidlsarbda.jpg' 
>>> mydf 
array([('foobarasdf.tif', 0.0), ('arghtidlsarbda.jpg', 0.0)], 
     dtype=[('file_name', '|O8'), ('file_size_mb', '<f8')]) 

Es un contra el espíritu del concepto matriz a tienen elementos de longitud variable, pero esto es lo más cerca que se puede obtener. La idea de una matriz es que los elementos se almacenen en la memoria en direcciones de memoria bien definidas y espaciadas regularmente, lo que prohíbe los elementos de longitud variable. Al almacenar los punteros en una cadena en una matriz, uno puede eludir esta limitación. (Esto es básicamente lo que hace el ejemplo anterior.)

+0

gracias por eso, solo estoy cambiando el idioma R y básicamente quería un tipo de objeto de marco de datos, ¡y esto funciona muy bien! –

+3

Comentario tardío: si se está moviendo desde R, considere el objeto pandas.DataFrame, que le resultará muy familiar y manejará bien las cadenas. – mdurant

Cuestiones relacionadas