Reputation: 1627
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.
Upvotes: 0
Views: 1800
Reputation: 8510
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
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
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
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
Upvotes: 2