3

I have a pandas Series, sufficiently small so I can read all items (about 80), but too big for the size of the screen.

Is there some python command ou ipython (notebook) magic command or pandas function to columnate that list or Series so I can read it entirely without scrolling down and up?

I'm basically looking for the equivalent of the column command in bash.

For example, I have a Series like this:

A      76
B      56
C      42
D      31
E      31
F      25
G      24

And let's say that my screen is so small that I need to scroll down to see after the B row. What I'd like is something like this:

A    76        C    42        E    31        G    24
B    56        D    31        F    25
jrjc
  • 21,103
  • 9
  • 64
  • 78
  • have a look at that question and the accepted answer: https://stackoverflow.com/questions/11707586/python-pandas-widen-output-display Is this what you want to do? – chris-sc Aug 11 '15 at 14:43
  • No, this is what I'm doing now to display more than X rows. The thing is that I have 1 column, and I'd like it displayed with multiple columns so all data can fit in the screen. – jrjc Aug 11 '15 at 14:53
  • What is the "screen"? Is it a terminal? Is it HTML? Is the number of columns in a terminal always going to be consistent? – kylieCatt Aug 11 '15 at 15:05
  • The screen is the size the window of the terminal or of the ipython notebook page. – jrjc Aug 11 '15 at 15:11
  • I'm not sure but I'd think about looking to numpy for a solution as numpy output does tend more towards this style of output (though obviously what it is missing are the indexes) – JohnE Aug 11 '15 at 15:11
  • @JohnE Maybe, but if the output formatting in the interactive console is so important to change the framework for the data, wouldn't it make more sense to write some `print_nice` function and really `print` the data? – chris-sc Aug 11 '15 at 15:20
  • @chris-sc Sure. Just looking for something easier than that, but may not be possible. – JohnE Aug 11 '15 at 15:21

2 Answers2

3

The following non-numpy/pandas solution might give you some inspiration:

import itertools

rows =  [("A", 76),  ("B", 56), ("C", 42), ("D", 31), ("E", 31), ("F", 25), ("G", 24)]

def print_multi_cols(lrows, split_at=5, space_each=4):
    for row in itertools.izip(*itertools.izip_longest(*[iter(lrows)]*split_at, fillvalue=(" ", " "))):
        for col in row:
            print " ".join(["%-*s" % (space_each, item) for item in col]),
        print

print_multi_cols(rows, 2)
print_multi_cols(rows, 3)

This gives the following output:

A     76      C     42      E     31      G     24     
B     56      D     31      F     25                   

A     76      D     31      G     24     
B     56      E     31                   
C     42      F     25

You would need to convert your series before this could be used. Tested using Python 2.7.

Or for a bit more control over the justification, it could be modified as follows:

import itertools

rows =  [("A", 9),  ("B", 56), ("C", 42), ("D", 31), ("E", 31), ("F", 25), ("G", 999)]

def print_multi_cols(lrows, split_at=5, space_each=4, left_justify=None):
    if not left_justify:
        left_justify = [True] * len(lrows[0])

    for row in itertools.izip(*itertools.izip_longest(*[iter(lrows)]*split_at, fillvalue=(" ", " "))):
        for col in row:
            print " ".join([("%-*s " if left else "%*s ") % (space_each, item) for item, left in itertools.izip(col, left_justify)]),
        print
    print

print_multi_cols(rows, split_at=5, space_each=3, left_justify=[True, False])

Giving:

A      9  F     25 
B     56  G    999 
C     42           
D     31           
E     31
Martin Evans
  • 45,791
  • 17
  • 81
  • 97
  • Thanks, it looks what I want. To pass a `Series` object you need to do `my_series.reset_index().values`. There may be a nicer way to pass the Series but I couldn't find. Thanks anyway, I'll wait before accepting in case someone comes with another solution. – jrjc Aug 11 '15 at 16:01
3

Using the idea of a show function (with some loops, but since data that can be shown that way is small, it should be fine).

def show(series, cols=6):                                                        
    rows = int(np.ceil(len(series)/float(cols)))                                 
    indices = series.index                                                       

    ind_loop = 0                                                                 
    for row in range(rows):                                                      
        ind = indices[ind_loop:ind_loop+cols]                                    
        dat = series[ind]                                                        
        comb = zip(ind, dat)                                                     
        print_str = ""                                                           
        for num in range(len(dat)):                                              
            print_str += "{{{0}: <10}} ".format(num)                             

        print(print_str.format(*comb))                                           
        ind_loop += cols                                                         

ser = pd.Series(range(20))                                                                                                                                                        
show(ser, cols=6) 

(0, 0)     (1, 1)     (2, 2)     (3, 3)     (4, 4)     (5, 5)                     
(6, 6)     (7, 7)     (8, 8)     (9, 9)     (10, 10)   (11, 11)
(12, 12)   (13, 13)   (14, 14)   (15, 15)   (16, 16)   (17, 17)
(18, 18)   (19, 19)

You could adjust the print to show something like index : value if you like.

chris-sc
  • 1,698
  • 11
  • 21