How to save a pandas DataFrame table as a png
Pandas allows you to plot tables using matplotlib (details here).
Usually this plots the table directly onto a plot (with axes and everything) which is not what you want. However, these can be removed first:
import matplotlib.pyplot as plt
import pandas as pd
from pandas.table.plotting import table # EDIT: see deprecation warnings below
ax = plt.subplot(111, frame_on=False) # no visible frame
ax.xaxis.set_visible(False) # hide the x axis
ax.yaxis.set_visible(False) # hide the y axis
table(ax, df) # where df is your data frame
plt.savefig('mytable.png')
The output might not be the prettiest but you can find additional arguments for the table() function here.
Also thanks to this post for info on how to remove axes in matplotlib.
EDIT:
Here is a (admittedly quite hacky) way of simulating multi-indexes when plotting using the method above. If you have a multi-index data frame called df that looks like:
first second
bar one 1.991802
two 0.403415
baz one -1.024986
two -0.522366
foo one 0.350297
two -0.444106
qux one -0.472536
two 0.999393
dtype: float64
First reset the indexes so they become normal columns
df = df.reset_index()
df
first second 0
0 bar one 1.991802
1 bar two 0.403415
2 baz one -1.024986
3 baz two -0.522366
4 foo one 0.350297
5 foo two -0.444106
6 qux one -0.472536
7 qux two 0.999393
Remove all duplicates from the higher order multi-index columns by setting them to an empty string (in my example I only have duplicate indexes in "first"):
df.ix[df.duplicated('first') , 'first'] = '' # see deprecation warnings below
df
first second 0
0 bar one 1.991802
1 two 0.403415
2 baz one -1.024986
3 two -0.522366
4 foo one 0.350297
5 two -0.444106
6 qux one -0.472536
7 two 0.999393
Change the column names over your "indexes" to the empty string
new_cols = df.columns.values
new_cols[:2] = '','' # since my index columns are the two left-most on the table
df.columns = new_cols
Now call the table function but set all the row labels in the table to the empty string (this makes sure the actual indexes of your plot are not displayed):
table(ax, df, rowLabels=['']*df.shape[0], loc='center')
et voila:
Your not-so-pretty but totally functional multi-indexed table.
EDIT: DEPRECATION WARNINGS
As pointed out in the comments, the import statement for table
:
from pandas.tools.plotting import table
is now deprecated in newer versions of pandas in favour of:
from pandas.plotting import table
EDIT: DEPRECATION WARNINGS 2
The ix
indexer has now been fully deprecated so we should use the loc
indexer instead. Replace:
df.ix[df.duplicated('first') , 'first'] = ''
with
df.loc[df.duplicated('first') , 'first'] = ''
How to save the Pandas dataframe/series data as a figure?
Option-1: use matplotlib table functionality, with some additional styling:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame()
df['date'] = ['2016-04-01', '2016-04-02', '2016-04-03']
df['calories'] = [2200, 2100, 1500]
df['sleep hours'] = [8, 7.5, 8.2]
df['gym'] = [True, False, False]
def render_mpl_table(data, col_width=3.0, row_height=0.625, font_size=14,
header_color='#40466e', row_colors=['#f1f1f2', 'w'], edge_color='w',
bbox=[0, 0, 1, 1], header_columns=0,
ax=None, **kwargs):
if ax is None:
size = (np.array(data.shape[::-1]) + np.array([0, 1])) * np.array([col_width, row_height])
fig, ax = plt.subplots(figsize=size)
ax.axis('off')
mpl_table = ax.table(cellText=data.values, bbox=bbox, colLabels=data.columns, **kwargs)
mpl_table.auto_set_font_size(False)
mpl_table.set_fontsize(font_size)
for k, cell in mpl_table._cells.items():
cell.set_edgecolor(edge_color)
if k[0] == 0 or k[1] < header_columns:
cell.set_text_props(weight='bold', color='w')
cell.set_facecolor(header_color)
else:
cell.set_facecolor(row_colors[k[0]%len(row_colors) ])
return ax.get_figure(), ax
fig,ax = render_mpl_table(df, header_columns=0, col_width=2.0)
fig.savefig("table_mpl.png")
Options-2 Use Plotly + kaleido
import plotly.figure_factory as ff
import pandas as pd
df = pd.DataFrame()
df['date'] = ['2016-04-01', '2016-04-02', '2016-04-03']
df['calories'] = [2200, 2100, 1500]
df['sleep hours'] = [8, 7.5, 8.2]
df['gym'] = [True, False, False]
fig = ff.create_table(df)
fig.update_layout(
autosize=False,
width=500,
height=200,
)
fig.write_image("table_plotly.png", scale=2)
fig.show()
For the above, the font size can be changed using the font
attribute:
fig.update_layout(
autosize=False,
width=500,
height=200,
font={'size':8}
)
Exporting a python dataframe + text element to an image
You can add the line df.index.name = pd.Timestamp('now').replace(microsecond=0)
to add the timestamp on the first row:
To add the line you can use .style.set_table_styles
:
data = {'Type': ['Type 1', 'Type 2', 'Type 3'], 'Value': [20, 21, 19]}
df = pd.DataFrame(data)
df.index.name = pd.Timestamp('now').replace(microsecond=0)
df.loc[len(df)] = ['Total',df['Value'].sum()]
test = df.style.set_table_styles([{'selector' : '.row3','props' : [('border-top','3px solid black')]}])
dfi.export(test, 'table.png')
Pandas - How to Save A Styled Dataframe to Image
Was able to change how I was using dataframe-image on the styler object and got it working. Passing it into the export() function rather than calling it off the object directly seems to be the right way to do this.
The .render() did get the HTML but was often losing much of the styling when converting it to image or when not viewed with Ipython HTML display. See comparision below.
Working Code:
import pandas as pd
import numpy as np
import dataframe_image as dfi
col_name = 'TestColumn'
temp_df = pd.DataFrame({'TestColumn':['A','B','A',np.nan]})
t1 = (temp_df[col_name].fillna("Unknown").value_counts()/len(temp_df)*100).to_frame().reset_index()
t1.rename(columns={'index':' '}, inplace=True)
t1[' '] = t1[' '].astype(str)
style_test = t1.style.bar(subset=[col_name], color='#5e81f2', vmax=100, vmin=0).set_table_attributes('style="font-size: 17px"').set_properties(
**{'color': 'black !important',
'border': '1px black solid !important'}
).set_table_styles([{
'selector': 'th',
'props': [('border', '1px black solid !important')]
}]).set_properties( **{'width': '500px'}).hide_index().set_properties(subset=[" "], **{'text-align': 'left'})
dfi.export(style_test, 'successful_test.png')
Option for dataframe-image module (convert a styled DataFrame to image) that the creator stopped updating and supporting
You could use pandas
.to_html()
, then use imgkit
to write to file.
import pandas as pd
import imgkit
def csv_to_image(csv_file,name_file):
df = pd.read_csv(csv_file)
df = df.style.set_table_styles([dict(selector='th', props=[('text-align', 'center'),('background-color', '#40466e'),('color', 'white')])])
df.set_properties(**{'text-align': 'center'}).hide(axis='index')
pd.set_option('colheader_justify', 'center')
html = df.to_html()
imgkit.from_string(html, name_file + ".png")
Can I save a table/dataframe to a file (like png/jpg) in python?
Assuming this table is a pandas DataFrame, this library might help:
www.dexplo.org/dataframe_image/
This library would export pandas DataFrames in a jupyter notebook fashioned way.
Example usage:
import pandas as pd
import dataframe_image as dfi
df = pd.DataFrame({'key':[1,2,3],'val':['a','b','c']})
dfi.export(df, 'dataframe.png')
Related Topics
Reload Flask App When Template File Changes
How to Convert a Password into Asterisks While It Is Being Entered
Creating Lowpass Filter in Scipy - Understanding Methods and Units
Python Generator That Groups Another Iterable into Groups of N
Python CSV.Reader: How to Return to the Top of the File
Comments Not Working in Jinja2
What Exactly Is Python's Iterator Protocol
Differencebetween Exec_Command and Send with Invoke_Shell() on Paramiko
Why Does the 'Is' Operator Behave Differently in a Script VS the Repl
Python Saving Multiple Figures into One PDF File
Combining Two Series into a Dataframe in Pandas
Take Multiple Lists into Dataframe
Correct Style for Python Functions That Mutate the Argument
How to Fix "Webdriverexception: Message: Connection Refused"