Search code examples
python2dtabular

2D table format Python


I want to create a 2D table format from my data stored in a dictionary.

Example:

d = {'ID1':[('Experiment1', 40), (Experiment2, 59), (Experiment3, 65)],    
 'ID2':[('Experiment1', 68), (Experiment2, 21), (Experiment3, 39)],   
 'ID3':[('Experiment1', 57), (Experiment2, 15), (Experiment4, 99)]}

Should give the following table:

    Experiment1     Experiment2     Experiment3     Experiment4

ID1 ...40................................59...............................65................................''
ID2....68...............................21................................39................................''
ID3....57...............................15................................''..................................99

Where IDx are the row labels and Experimentx are the column names. If a dataset don't have a value to the column name, then an empty string should be added as placeholder.

Can anybody help how to do this? Is there any ready format in python, which I could use?


Solution

  • A quick and dirty implementation (fixing your typos in the question ...)

    d = {'ID1':[('Experiment1', 40), ('Experiment2', 59), ('Experiment3', 65)],    
     'ID2':[('Experiment1', 68), ('Experiment2', 21), ('Experiment3', 39)],   
     'ID3':[('Experiment1', 57), ('Experiment2', 15), ('Experiment4', 99)]}
    
    COLUMN_WIDTH = 20
    STRING_WHEN_MISSING = '""'
    PADDING_STRING = "."
    
    
    #first determine what are the columns - from the first line
    columns = ["id"] #there is always at least the id column
    columns = columns + [colName for (colName, colValue) in d.items()[0][1]]
    
    print "".join([ col.ljust(COLUMN_WIDTH) for col in columns])
    
    #browse the lines, order by ID Ascending
    for (rowId, rowValues) in sorted(d.items(), key= lambda x: x[0].lower()):
        #print rowId
        #print rowValues
        rowValuesDict = dict(rowValues) #make it a dict with access by key
        rowValuesDict["id"] = rowId
        #print rowValuesDict
        print "".join([ str(rowValuesDict.get(col, STRING_WHEN_MISSING)).ljust(COLUMN_WIDTH, PADDING_STRING) for col in columns])
    

    This prints out :

    id                  Experiment1         Experiment2         Experiment3         
    ID1.................40..................59..................65..................
    ID2.................68..................21..................39..................
    ID3.................57..................15..................""..................
    

    Note :

    The format of your orginal dictionary is a bit strange ... I would expect more something like this :

    d = [('ID1',{'Experiment1': 40, 'Experiment2':59, 'Experiment3':65}),    
         ('ID2',{'Experiment1': 68, 'Experiment2':21, 'Experiment3':39})] 
    

    Some Comments:

    For this kind of things, you want to read about some Python string methods : center(), ljust() and rjust() that add characters before and/or after a string to force its total width.

    Appart from that, the idea is mostly about looping through lists/dictionaries and extract value.

    Note the use of dict method get() that allows to have a default value when no value exists for a given key.