2011-02-19 22 views
7

¿Existe alguna manera elegante de explotar la función de espaciado correcta de print numpy.array para obtener una matriz 2D, con las etiquetas adecuadas, que se alinee correctamente? Por ejemplo, dada una matriz con 4 filas y 5 columnas, ¿cómo puedo proporcionar la matriz y las listas de tamaño adecuado correspondientes a las columnas de la fila y el encabezado para generar algún resultado que se vea así?¿Cómo imprimo una matriz numpy alineada con etiquetas de fila y columna (de texto)?

 A B C D E 
Z [[ 85 86 87 88 89] 
Y [ 90 191 192 93 94] 
X [ 95 96 97 98 99] 
W [100 101 102 103 104]] 

Si ingenuamente trato:

import numpy 
x = numpy.array([[85, 86, 87, 88, 89], \ 
       [90, 191, 192, 93, 94], \ 
       [95, 96, 97, 98, 99], \ 
       [100,101,102,103,104]]) 

row_labels = ['Z', 'Y', 'X', 'W'] 


print "  A B C D E" 
for row, row_index in enumerate(x): 
    print row_labels[row_index], row 

me sale:

 A B C D E 
Z [85 86 87 88 89] 
Y [90 191 192 93 94] 
X [95 96 97 98 99] 
W [100 101 102 103 104] 

¿Hay alguna manera que puedo conseguir cosas que se alinean de forma inteligente? Definitivamente estoy abierto a usar cualquier otra biblioteca si hay una mejor manera de resolver mi problema.

Respuesta

6

Suponiendo que todos los números de la matriz tener como máximo 3 dígitos, se puede sustituir la última parte con esto:

print "  A B C D E" 
for row_label, row in zip(row_labels, x): 
    print '%s [%s]' % (row_label, ' '.join('%03s' % i for i in row)) 

que da salida:

 A B C D E 
Z [ 85 86 87 88 89] 
Y [ 90 191 192 93 94] 
X [ 95 96 97 98 99] 
W [100 101 102 103 104] 

formato con '%03s' resultados en una serie de longitud 3 con relleno izquierdo (usando espacios). Use '%04s' para la longitud 4 y así sucesivamente. El completo format string syntax se explica en la documentación de Python.

5

Aquí hay una manera de aprovechar las funciones de impresión de matriz. Probablemente no lo usaría, ¡pero está muy cerca de cumplir con sus requisitos!

a = np.random.rand(5,4) 
x = np.array('col1 col2 col3 col4'.split()) 
y = np.array('row1 row2 row3 row4 row5'.split()) 
b = numpy.zeros((6,5),object) 
b[1:,1:]=a 
b[0,1:]=x 
b[1:,0]=y 
b[0,0]='' 
printer = np.vectorize(lambda x:'{0:5}'.format(x,)) 
print printer(b).astype(object) 

[[  col1 col2 col3 col4] 
[row1 0.95 0.71 0.03 0.56] 
[row2 0.56 0.46 0.35 0.90] 
[row3 0.24 0.08 0.29 0.40] 
[row4 0.90 0.44 0.69 0.48] 
[row5 0.27 0.10 0.62 0.04]] 
5

Puede utilizar IPython notebook + Pandas para eso. Escriba su ejemplo original en IPython portátil:

import numpy 
x = numpy.array([[85, 86, 87, 88, 89], 
       [90, 191, 192, 93, 94], 
       [95, 96, 97, 98, 99], 
       [100,101,102,103,104]]) 

row_labels = ['Z', 'Y', 'X', 'W'] 
column_labels = ['A', 'B', 'C', 'D', 'E'] 

continuación, crear una trama de datos:

import pandas 
df = pandas.DataFrame(x, columns=column_labels, index=row_labels) 

ya continuación, ver:

enter image description here

0

Este código es esencialmente una implementación de la anterior scoffey , pero no tiene la limitación de tres caracteres y es un poco más poderoso. Aquí está mi código:

def format__1(digits,num): 
     if digits<len(str(num)): 
      raise Exception("digits<len(str(num))") 
     return ' '*(digits-len(str(num))) + str(num) 
    def printmat(arr,row_labels=[], col_labels=[]): #print a 2d numpy array (maybe) or nested list 
     max_chars = max([len(str(item)) for item in flattenList(arr)+col_labels]) #the maximum number of chars required to display any item in list 
     if row_labels==[] and col_labels==[]: 
      for row in arr: 
       print '[%s]' %(' '.join(format__1(max_chars,i) for i in row)) 
     elif row_labels!=[] and col_labels!=[]: 
      rw = max([len(str(item)) for item in row_labels]) #max char width of row__labels 
      print '%s %s' % (' '*(rw+1), ' '.join(format__1(max_chars,i) for i in col_labels)) 
      for row_label, row in zip(row_labels, arr): 
       print '%s [%s]' % (format__1(rw,row_label), ' '.join(format__1(max_chars,i) for i in row)) 
     else: 
      raise Exception("This case is not implemented...either both row_labels and col_labels must be given or neither.") 

corriendo

import numpy 
    x = numpy.array([[85, 86, 87, 88, 89], 
        [90, 191, 192, 93, 94], 
        [95, 96, 97, 98, 99], 
        [100,101,102,103,104]]) 
    row_labels = ['Z', 'Y', 'X', 'W'] 
    column_labels = ['A', 'B', 'C', 'D', 'E'] 
    printmat(x,row_labels=row_labels, col_labels=column_labels) 

da

  A B C D E 
    Z [ 85 86 87 88 89] 
    Y [ 90 191 192 93 94] 
    X [ 95 96 97 98 99] 
    W [100 101 102 103 104] 

Esta sería también la salida si 'x' eran simplemente una lista de Python anidada en lugar de una matriz numpy.

Cuestiones relacionadas