How to print a aligned numpy array with (text) rows and columns?

Is there an elegant way to use the correct print numpy.array spacing function to get a 2D array with matching labels that aligns correctly? For example, given an array with 4 rows and 5 columns, how can I provide a list of the array and the corresponding size corresponding to the columns of the row and header to generate some output that looks like this?

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

If I naively try:

 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 " ABCDE" for row, row_index in enumerate(x): print row_labels[row_index], row 

I get:

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

Is there a way I can make things line up reasonably? I am definitely open to using any other library if there is a better way to solve my problem.

+7
source share
4 answers

Assuming that all matrix numbers have at most 3 digits, you can replace the last part as follows:

 print " ABCDE" for row_label, row in zip(row_labels, x): print '%s [%s]' % (row_label, ' '.join('%03s' % i for i in row)) 

What outputs:

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

Formatting with '%03s' results in a string of length 3 with left padding (using spaces). Use '%04s' for length 4 and so on. The full line syntax is explained in the Python documentation.

+6
source

Here you can use the print functions of the array. I probably won’t use it, but it comes close to your requirements!

 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
source

You can use IPython notebook + Pandas for this. Enter your original example into an IPython laptop:

 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'] 

Then create a DataFrame:

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

And then view it:

enter image description here

+5
source

This code is essentially the scoffey implementation above, but it does not have three character restrictions and is slightly more powerful. Here is my code:

  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.") 

working

  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) 

gives

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

This will also be the output if "x" was just a nested python list instead of a numpy array.

0
source

All Articles