2012-06-19 80 views
14

Tengo una matriz multidimensional (usando numpy) a la que me gustaría agregar encabezados de fila/columna. Los datos son en realidad 7x12x12, pero puede representar así:Agregar encabezados de fila/columna a Numpy Matrices

A=[[[0, 1, 2, 3, 4, 5], 
     [1, 0, 3, 4, 5, 6], 
     [2, 3, 0, 5, 6, 7], 
     [3, 4, 5, 0, 7, 8], 
     [4, 5, 6, 7, 0, 9], 
     [5, 6, 7, 8, 9, 0]] 


    [[0, 1, 2, 3, 4, 5], 
     [1, 0, 3, 4, 5, 6], 
     [2, 3, 0, 5, 6, 7], 
     [3, 4, 5, 0, 7, 8], 
     [4, 5, 6, 7, 0, 9], 
     [5, 6, 7, 8, 9, 0]]] 

donde A es mi matriz de 2x6x6.

En cualquier caso, ¿Cómo se inserta a través de los encabezados de la primera fila y la primera columna, de manera que cada matriz se ve así:

 A, a, b, c, d, e, f 
     a, 0, 1, 2, 3, 4, 5, 
     b, 1, 0, 3, 4, 5, 6, 
     c, 2, 3, 0, 5, 6, 7, 
     d, 3, 4, 5, 0, 7, 8, 
     e, 4, 5, 6, 7, 0, 9, 
     f, 5, 6, 7, 8, 9, 0 

en mi archivo de salida CSV?

Ahora mismo lo que he hecho es hacer la matriz 7x13x13 e insertar los datos de manera que tenga una fila y una columna de 0, pero prefiero las cadenas. Supongo que podría simplemente escribir una macro excel para reemplazar los ceros con cadenas ... El problema es que Numpy no puede convertir una cadena en flotante, si trato de reasignar esos 0 como las cadenas que quiero.

+0

Im que no están familiarizados con numpy pero esto sería muy recta reenviar si solo fueran listas. ¿Sería aceptable una solución de ese orden? ¿Puedes convertir matrices numpy en listas? –

+0

La manera en que funcionan las matrices numpy, pueden funcionar como listas de listas, por lo que puede iterar sobre ellas por su cuenta. – JAB

Respuesta

9

Numpy se encargará de la matriz de n dimensiones, pero puede que las instalaciones estén limitadas a 2 matrices dimensionales. Ni siquiera está seguro de cómo quiere que se vea el archivo de salida.

Muchas personas que desearían tener columnas con nombre pasan por alto las capacidades recarray() de numpy. Que bueno saber pero que solo "nombra" una dimensión.

Para dos dimensiones, Pandas es genial.

In [275]: DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6])], 
    .....:      orient='index', columns=['one', 'two', 'three']) 
Out[275]: 
    one two three 
A 1 2  3 
B 4 5  6 

Si la salida es el único problema que está tratando de resolver aquí, probablemente sólo se adhieren con unas pocas líneas de código magia mano, ya que será menos pesada que la instalación de otro paquete para una característica.

+0

Pandas es exactamente lo que he estado buscando. – emmagras

1

No conozco ningún método para agregar encabezados a la matriz (aunque lo encontraría útil). Lo que haría es crear una clase pequeña que me imprima el objeto, sobrecargando la función __str__.

Algo como esto:

class myMat: 
    def __init__(self, mat, name): 
     self.mat = mat 
     self.name = name 
     self.head = ['a','b','c','d','e','f'] 
     self.sep = ',' 

    def __str__(self): 
     s = "%s%s"%(self.name,self.sep) 
     for x in self.head: 
      s += "%s%s"%(x,self.sep) 
     s = s[:-len(self.sep)] + '\n' 

     for i in range(len(self.mat)): 
      row = self.mat[i] 
      s += "%s%s"%(self.head[i],self.sep) 
      for x in row: 
       s += "%s%s"%(str(x),self.sep) 
      s += '\n' 
     s = s[:-len(self.sep)-len('\n')] 

     return s 

Entonces usted podría fácilmente imprimirlos con los encabezados, usando el siguiente código:

print myMat(A,'A') 
print myMat(B,'B') 
+0

Esto parece prometedor. Al tratar de extraer mi pregunta, confundí las cosas, ya que la matriz grande no está compuesta de matrices más pequeñas etiquetadas. Intenté dividirlo e implementar tu sugerencia, pero no funciona. Para empezar, tengo un "índice de lista fuera de rango" en esta línea s + = "% s% s"% (self.head [i], self.sep) ¿Cómo cambiaría su sugerencia dado que A es el solo matriz, en lugar de tratar con una matriz que es una compilación de matrices? – emmagras

+0

Supongo que obtiene un error de índice fuera de rango debido al diferente tamaño de las matrices. En este momento, este código solo funcionará con matrices de 6x6 (es decir, len (['a', 'b', 'c', 'd', 'e', ​​'f'])). Simplemente cambie la línea que define self.head al tamaño de su matriz (por ejemplo, si sus matrices son 3x3, la línea debería verse como self.head = ['a', 'b', 'c']). ¡Espero que esto ayude! –

3

Creo que esto hace el truco genéricamente

entrada

mats = array([[[0, 1, 2, 3, 4, 5], 
    [1, 0, 3, 4, 5, 6], 
    [2, 3, 0, 5, 6, 7], 
    [3, 4, 5, 0, 7, 8], 
    [4, 5, 6, 7, 0, 9], 
    [5, 6, 7, 8, 9, 0]], 

    [[0, 1, 2, 3, 4, 5], 
    [1, 0, 3, 4, 5, 6], 
    [2, 3, 0, 5, 6, 7], 
    [3, 4, 5, 0, 7, 8], 
    [4, 5, 6, 7, 0, 9], 
    [5, 6, 7, 8, 9, 0]]]) 

Código

# Recursively makes pyramiding column and row headers 
def make_head(n): 
    pre = '' 
    if n/26: 
     pre = make_head(n/26-1) 

    alph = "abcdefghijklmnopqrstuvwxyz" 
    pre+= alph[n%26] 
    return pre 

# Generator object to create header items for n-rows or n-cols 
def gen_header(nitems): 
    n = -1 
    while n<nitems: 
     n+=1 
     yield make_head(n) 

# Convert numpy to list 
lmats = mats.tolist() 

# Loop through each "matrix" 
for mat in lmats: 
    # Pre store number of columns as we modify it before working rows 
    ncols = len(mat[0]) 

    # add header value to front of each row from generator object 
    for row,hd in zip(mat,gen_header(len(mat))): 
     row.insert(0,hd) 

    # Create a "header" line for all the columns 
    col_hd = [hd for hd in gen_header(ncols-1)] 
    col_hd.insert(0,"A") 

    # Insert header line into lead row of matrix 
    mat.insert(0,col_hd) 

# Convert back to numpy 
mats = numpy.array(lmats) 

de salida (valor almacenado en esteras):

array([[['A', 'a', 'b', 'c', 'd', 'e', 'f'], 
     ['a', '0', '1', '2', '3', '4', '5'], 
     ['b', '1', '0', '3', '4', '5', '6'], 
     ['c', '2', '3', '0', '5', '6', '7'], 
     ['d', '3', '4', '5', '0', '7', '8'], 
     ['e', '4', '5', '6', '7', '0', '9'], 
     ['f', '5', '6', '7', '8', '9', '0']], 

     [['A', 'a', 'b', 'c', 'd', 'e', 'f'], 
     ['a', '0', '1', '2', '3', '4', '5'], 
     ['b', '1', '0', '3', '4', '5', '6'], 
     ['c', '2', '3', '0', '5', '6', '7'], 
     ['d', '3', '4', '5', '0', '7', '8'], 
     ['e', '4', '5', '6', '7', '0', '9'], 
     ['f', '5', '6', '7', '8', '9', '0']]], 
     dtype='|S4') 
+0

Obtengo un error. El objeto ''numpy.ndarray' 'no tiene ningún atributo' insert'' ¿Alguna sugerencia de solución? – emmagras

+0

Trabajo alrededor incluido. Convertí las esteras numpy en listas, hice las operaciones y volví a convertirlas. Las rutinas de inserción de Numpy son bastante estúpidas o no veo cómo son útiles –

+0

Gracias. Finalmente lo descubrí con esto. – emmagras

1

No es muy seguro, pero puede considerar tener un vistazo a Pandas.

21

Con pandas.DataFrame.to_csv puede escribir las columnas y el índice a un archivo:

import numpy as np 
import pandas as pd 

A = np.random.randint(0, 10, size=36).reshape(6, 6) 
names = [_ for _ in 'abcdef'] 
df = pd.DataFrame(A, index=names, columns=names) 
df.to_csv('df.csv', index=True, header=True, sep=' ') 

le dará la df.csv siguiente archivo:

a b c d e f 
a 1 5 5 0 4 4 
b 2 7 5 4 0 9 
c 6 5 6 9 7 0 
d 4 3 7 9 9 3 
e 8 1 5 1 9 0 
f 2 8 0 0 5 1  
+1

Esto es especialmente útil ya que incluye los comandos de importación y la información sobre cómo escribir en el archivo. Increíble. – emmagras

+0

Gracias. Si dices que mi respuesta es asombrosa, considera que se puede votar mejor ;-) – bmu