0

I am performing computation on complex query and getting below dictionary as final output and now want to print that dict in html format without hardcoding column names as it is dynamic.

If column is not there then add 0 in the report.

data = {'Author1': defaultdict(<class 'dict'>,
                        {'Microsoft': 248,
                         'Ubuntu': 24,
                         'IOS': 24,
                         'Solaris': 24,
                         'C': 248}),
 'Author2': defaultdict(<class 'dict'>,
                           {'Microsoft': 38,
                            'Ubuntu': 38,
                            'IOS': 38,
                            'Go': 38,
                            'C': 38}),
 'Author3': defaultdict(<class 'dict'>,
                    {'Microsoft': 2,
                     'IOS': 2,
                     'Go': 2,
                     'C': 2})}

Output

 Name       Microsoft  Ubuntu IOS Go Solaris C
Author1       248        24   24  0   24     248  
Author2        38        38    38 38   0      38
Author3        2         0     2  2    0      2

code:

html = '<table><tr><th>' + '</th><th>'.join(data.keys()) + '</th></tr>'

for row in zip(*data.values()):
    html += '<tr><td>' + '</td><td>'.join(row) + '</td></tr>'

html += '</table>'

print(html)

This code errors out bec of default dict inside a dictionary, which needs to be removed.

1
  • If you get an error, you must show the full error message. Anyway, remember that a dict does not preserve order and I do not think that what you need are defaultdic(dict, ...) Commented Feb 22, 2017 at 15:06

1 Answer 1

2

how about using pandas it does all the job for you

import pandas
df = pandas.DataFrame.from_dict(data)
html = """<!DOCTYPE html>
<html>
    <body>
{body}
    </body>
</html>
"""
with open("test.html","w") as file:
    file.write( html.format(body=df.to_html(na_rep="0")) )

this result in this table

enter image description here

use .T to transpose the table

with open("test2.html","w") as file:
    file.write( html.format(body=df.T.to_html(na_rep="0")) )

and result in

enter image description here


without pandas, them I would go like this

html = """<!DOCTYPE html>
<html>
    <body>
{body}
    </body>
</html>
"""

table="""
<table border="1" class="dataframe">
  <thead>
{thead}
  </thead>
  <tbody>
{tbody}
  </tbody>
</table>
"""

thead="""
<tr style="text-align: right;">
{th}
</tr>
"""
th="""<th>{}</th>\n"""
td="""<td>{}</td>\n"""
tr="""<tr>{}</tr>\n"""

def manual_table(data, colums):
    head = thead.format(th= "".join( map(th.format,["Name"]+colums)))
    pieces=[]
    for autor, value in data.items():
        temp = [autor]
        temp.extend( value.get(c,0) for c in colums )
        pieces.append(tr.format( "".join(td.format(x) for x in temp )) )
    body = "\n".join(pieces)
    return table.format(thead=head, tbody=body)

colums="Microsoft  Ubuntu IOS Go Solaris C".split()

with open("test3.html","w") as file:
    file.write( html.format(body=manual_table(data, colums)))

first I build some templates, so I get something that I can read at the end, then I go inside out filling those templates accordingly and in the order that I impose by the colums variable.

this result in

enter image description here


One of the problem with your code is that you don't fetch the values in the correct order, one partial solution for that is

colums="Microsoft  Ubuntu IOS Go Solaris C".split()
for row in data.values():
    table += '<tr><td>' + '</td><td>'.join(str(row.get(c,0)) for c in colums) + '</td></tr>'

if you don't want to hard code the column's names, but get them from the data, then you can do this

>>> {k for v in data.values() for k in v }
{'C', 'IOS', 'Solaris', 'Ubuntu', 'Microsoft', 'Go'}
>>> 

about your question in the comments, yes you can and is very easy with sum, like for example

>>> df
           Author1  Author2  Author3
C            248.0     38.0      2.0
Go             NaN     38.0      2.0
IOS           24.0     38.0      2.0
Microsoft    248.0     38.0      2.0
Solaris       24.0      NaN      NaN
Ubuntu        24.0     38.0      NaN
>>> df["Total"] = df.T.sum()
>>> df
           Author1  Author2  Author3  Total
C            248.0     38.0      2.0  288.0
Go             NaN     38.0      2.0   40.0
IOS           24.0     38.0      2.0   64.0
Microsoft    248.0     38.0      2.0  288.0
Solaris       24.0      NaN      NaN   24.0
Ubuntu        24.0     38.0      NaN   62.0

just play around with it until you get the desire result, and check the documentation so you know all the toys it have

Sign up to request clarification or add additional context in comments.

4 Comments

Wow, na_rep='0' automatically convert the empty dicts to 0! Clean output despite the poor input... Nice
Using pandas looks great! Is it possible to add "Total" column in the table using pandas, Or do I need to compute myself before passing the values?
@Copperfield: I would like to add in pandas style colour to alternate row in table. Can you please let me know.
@VinodHC I'm not that familiar with pandas, maybe you can do something with the formatters parameter of to_html, but I don't know how, make a new question about it so a more knowledgeable user can help you with it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.