2012-05-24 24 views
12

Estoy tratando de agregar nombres de columnas a nudos ndarray, luego selecciono columnas por sus nombres. Pero no funciona. No puedo decir si el problema ocurre cuando agrego los nombres, o más tarde cuando intento llamarlos.Agregue nombres de columnas mediante programación a numpy ndarray

Aquí está mi código.

data = np.genfromtxt(csv_file, delimiter=',', dtype=np.float, skip_header=1) 

#Add headers 
csv_names = [ s.strip('"') for s in file(csv_file,'r').readline().strip().split(',')] 
data = data.astype(np.dtype([(n, 'float64') for n in csv_names])) 

diagnósticos basados ​​en dimensión coincide con lo que espero:

print len(csv_names) 
>> 108 
print data.shape 
>> (1652, 108) 

"data.dtype.names de impresión" también devuelve la salida esperada.

Pero cuando comienzo a llamar columnas por sus nombres de campo, ocurren cosas complicadas. La "columna" sigue siendo una matriz con 108 columnas ...

print data["EDUC"].shape 
>> (1652, 108) 

... y parece contener valores que faltan más que filas en el conjunto de datos.

print np.sum(np.isnan(data["EDUC"])) 
>> 27976 

¿Alguna idea de qué está mal aquí? Agregar encabezados debería ser una operación trivial, pero he estado luchando contra este error durante horas. ¡Ayuda!

Respuesta

13

el problema es que usted está pensando en términos de matrices de hoja de cálculo, mientras que Num Py usa diferentes conceptos.

Aquí es lo que usted debe saber sobre NumPy: matrices

  1. NumPy sólo contienen elementos de un solo tipo .
  2. Si necesita "columnas" tipo hoja de cálculo, este tipo debe ser tipo tupla. Dichas matrices se llaman arrays estructurados, porque sus elementos son estructuras (es decir, tuplas).

En su caso, NumPy sería por lo tanto llevar a su disposición regular de 2 dimensiones y producir una matriz dimensional uno cuyo tipo es una tupla 108-elemento (la matriz de hoja de cálculo que está pensando es de 2 dimensiones)

Probablemente, estas opciones se tomaron por razones de eficiencia: todos los elementos de una matriz tienen el mismo tipo y, por lo tanto, tienen el mismo tamaño: se puede acceder a ellos en un nivel bajo, de manera simple y rápida.

Ahora, como mostró el usuario545424, hay una respuesta simple de NumPy a lo que quiere hacer (genfromtxt() acepta un argumento names con nombres de columna).

Si desea convertir la matriz de una ndarray NumPy regular a una matriz estructurada, que puede hacer:

data.view(dtype=[(n, 'float64') for n in csv_names]).reshape(len(data)) 

(que estaban cerca: astype() que utilizó en lugar de view()).

También puede consultar las respuestas a algunas preguntas sobre Stackoverflow, incluidas Converting a 2D numpy array to a structured array y how to convert regular numpy array to record array?.

+0

Gracias - esto ayuda a aclarar las cosas conceptualmente. Pero todavía tengo algunas preguntas sobre este caso particular. Aquí, todas mis columnas son flotantes, y voy a hacer una gran cantidad de multiplicación de matrices, así que quiero mantener la estructura de 2d-array, sin necesidad de una matriz estructurada. Todo lo que quiero hacer es agregar nombres de campo. ¿Es eso posible? – Abe

+0

NB: genfromtxt importa el csv en el formato de tupla estructurado de numpy. Intenté todo lo que pude pensar para importar nombres de campo en formato de matriz, y nada funcionó. – Abe

+0

@Abe: aún puede realizar multiplicaciones de matrices: 'ver()' es simplemente otra forma de ver los * mismos * datos. Por lo tanto, puede trabajar tanto con la matriz de datos original como con la matriz 'view()' al mismo tiempo (la primera matriz es 2D, la segunda es 1D y está estructurada). – EOL

2

Por desgracia, no sé lo que está pasando cuando intenta agregar los nombres de campo, pero sí sé que se puede construir la matriz que desea directamente desde el archivo a través de

data = np.genfromtxt(csv_file, delimiter=',', names=True) 

EDIT:

parece que la adición de nombres de campo sólo funciona cuando la entrada es una lista de tuplas:

data = np.array(map(tuple,data), [(n, 'float64') for n in csv_names]) 
+0

Así es que las ndarrays pueden ser referenciadas por los nombres de los campos si se emiten como tuplas O se hace referencia por identificador de campo cuando se emiten como matrices --- ¿pero nunca ambas? Esa parece ser la forma en que funciona, pero no veo nada de eso en la documentación. – Abe

+0

Estoy comenzando a preguntarme si esto es un error. Es un comportamiento muy extraño hacer que el constructor de matriz actúe de forma diferente en función del tipo de estructura anidada en la que pasa. – user545424

+0

@ user545424: Puede comprender este comportamiento si conoce los principios en los que se basa NumPy (puede verificar mi respuesta, por ejemplo)) En pocas palabras: tuple() es una especie de "tipo fundamental" (como flotadores), para NumPy (por lo que obtienes una especie de matriz estructurada, cuando pasas tuplas), mientras que pasar listas o matrices como entrada significa "agregar otra dimensión "a la matriz (normalmente se obtiene una matriz de números). – EOL

Cuestiones relacionadas