2011-02-19 85 views
7

是否有任何优雅的方式来利用print numpy.array的正确间距功能来获得二维数组,并使用正确的标签进行正确对齐?例如,给定一个有4行和5列的数组,我该如何提供数组和适当大小的与行和列列相对应的列表来生成一些看起来像这样的输出?如何使用(文本)行和列标签打印对齐的numpy数组?

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

如果我天真的尝试:

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 

我得到:

 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] 

有什么办法,我可以得到的东西智能排队?如果有更好的方法来解决我的问题,我绝对愿意使用任何其他库。

回答

6

假设所有的矩阵号码最多有3个数字,你可以替换这最后一部分:

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

,输出:

 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] 

'%03s'结果格式长3串用左填充(使用空格)。使用'%04s'长度为4等等。完整的format string syntax在Python文档中有解释。

5

这是一种利用阵列打印功能的方法。我可能不会使用它,但它非常接近满足您的要求!

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

您可以使用IPython notebook + Pandas了点。在IPython的笔记本键入您的原来的例子:

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

然后创建一个数据框:

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

,然后查看它:

enter image description here

0

此代码基本上scoffey的上方的实现,但它没有三个字符的限制,并且更强大一些。 这里是我的代码:

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

运行

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) 

  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] 

这也将是输出,如果 'X' 只是一个嵌套的Python列表,而不是numpy的阵列。