Change the Color of Text Within a Pandas Dataframe HTML Table Python Using Styles and CSS

Change the color of text within a pandas dataframe html table python using styles and css

This takes a few steps:

First import HTML and re

from IPython.display import HTML
import re

You can get at the html pandas puts out via the to_html method.

df_html = df.to_html()

Next we are going to generate a random identifier for the html table and style we are going to create.

random_id = 'id%d' % np.random.choice(np.arange(1000000))

Because we are going to insert some style, we need to be careful to specify that this style will only be for our table. Now let's insert this into the df_html

df_html = re.sub(r'<table', r'<table id=%s ' % random_id, df_html)

And create a style tag. This is really up to you. I just added some hover effect.

style = """
<style>
table#{random_id} tr:hover {{background-color: #f5f5f5}}
</style>
""".format(random_id=random_id)

Finally, display it

HTML(style + df_html)

Function all in one.

def HTML_with_style(df, style=None, random_id=None):
from IPython.display import HTML
import numpy as np
import re

df_html = df.to_html()

if random_id is None:
random_id = 'id%d' % np.random.choice(np.arange(1000000))

if style is None:
style = """
<style>
table#{random_id} {{color: blue}}
</style>
""".format(random_id=random_id)
else:
new_style = []
s = re.sub(r'</?style>', '', style).strip()
for line in s.split('\n'):
line = line.strip()
if not re.match(r'^table', line):
line = re.sub(r'^', 'table ', line)
new_style.append(line)
new_style = ['<style>'] + new_style + ['</style>']

style = re.sub(r'table(#\S+)?', 'table#%s' % random_id, '\n'.join(new_style))

df_html = re.sub(r'<table', r'<table id=%s ' % random_id, df_html)

return HTML(style + df_html)

Use it like this:

HTML_with_style(df.head())

Sample Image

HTML_with_style(df.head(), '<style>table {color: red}</style>')

Sample Image

style = """
<style>
tr:nth-child(even) {color: green;}
tr:nth-child(odd) {color: aqua;}
</style>
"""
HTML_with_style(df.head(), style)

Sample Image

Learn CSS and go nuts!

Convert pandas df to html table and apply color to pandas row based on a criteria

You can try .style.apply and .set_table_styles

def highlight(row):
if row['revenue'] > 500:
return ['background-color: red'] * len(row)
else:
return [''] * len(row)

s = df.style.apply(highlight, axis=1)
s = s.set_table_styles([
{
'selector': '.col_heading',
'props': 'background-color: yellow; color: black;'
}
])

s.to_html('output.html')

Sample Image

Python formatting DataFrame table colours and borders

Possible solution is the following:

import pandas as pd

# create a table summary
index = pd.MultiIndex.from_tuples([("Type", ""),
("Alpha", "x"),
("Alpha", "y"),
("Alpha", "z"),
("Beta", "")])

data = [["a", "b", "c", "d"],
[1, 2, 3, 4], [5, 6, 7, 8],
[9, 10, 11, 12], [13, 14, 15, 16]]

table = pd.DataFrame(data = data,
index = index,
columns = pd.MultiIndex.from_product([["data"], ["","","",""]]))

# set styles
header = {'selector': 'thead, th',
'props': 'background-color: #00008b; color: white; text-align: center;'}

index_col = {'selector': 'th.row_heading',
'props': 'background-color: #5b9bd5; color: white; text-align: center;'}

types_row = {'selector': 'td.data.row0',
'props': 'background-color: #5b9bd5; color: white; text-align: center;'}

borders_horizontal = {'selector': '.row0, .row_heading.level0.row1, .row3',
'props': 'border-bottom: 2px solid #000066'}

borders_vertical = {'selector': '.row_heading.level1',
'props': 'border-right: 2px solid #000066'}

hide_row = {'selector': 'thead tr:nth-child(2)', 'props': [('display', 'none')]}

# apply stiles
style = table.style.set_table_styles([header, index_col, types_row,
borders_horizontal, borders_vertical,
hide_row])

style

Returns

Sample Image

Also you may find helpful to use print(table.style.render()) or print(style.to_html()) to get html tags and css styles those has been applied to pandas dataframe.

Color rows of pandas dataframe and convert to HTML table

As the error message indicates, you are trying to use the DataFrame.to_html() method on a Styler object, since df.style.apply returns a Styler object and not a DataFrame.

The docs say you can use the render() method to render the HTML.

Something like this:

style1 = df.style.apply(highlight_greaterthan,threshold=1.0,column=['C','B'], axis=1)
df_html = style1.render()

The output of style1.render() would be:

<style  type="text/css" >
#T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col0 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col1 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col2 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col3 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col4 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col0 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col1 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col2 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col3 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col4 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col0 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col1 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col2 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col3 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col4 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col0 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col1 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col2 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col3 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col4 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col0 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col1 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col2 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col3 {
background-color: yellow;
} #T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col4 {
background-color: yellow;
}</style>
<table id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3" >
<thead> <tr>
<th class="blank level0" ></th>
<th class="col_heading level0 col0" >A</th>
<th class="col_heading level0 col1" >B</th>
<th class="col_heading level0 col2" >C</th>
<th class="col_heading level0 col3" >D</th>
<th class="col_heading level0 col4" >E</th>
</tr></thead>
<tbody> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row0" class="row_heading level0 row0" >0</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col0" class="data row0 col0" >1</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col1" class="data row0 col1" >1.32921</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col2" class="data row0 col2" >nan</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col3" class="data row0 col3" >-0.31628</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row0_col4" class="data row0 col4" >-0.99081</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row1" class="row_heading level0 row1" >1</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row1_col0" class="data row1 col0" >2</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row1_col1" class="data row1 col1" >-1.07082</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row1_col2" class="data row1 col2" >-1.43871</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row1_col3" class="data row1 col3" >0.564417</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row1_col4" class="data row1 col4" >0.295722</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row2" class="row_heading level0 row2" >2</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row2_col0" class="data row2 col0" >3</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row2_col1" class="data row2 col1" >-1.6264</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row2_col2" class="data row2 col2" >0.219565</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row2_col3" class="data row2 col3" >0.678805</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row2_col4" class="data row2 col4" >1.88927</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row3" class="row_heading level0 row3" >3</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row3_col0" class="data row3 col0" >4</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row3_col1" class="data row3 col1" >0.961538</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row3_col2" class="data row3 col2" >0.104011</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row3_col3" class="data row3 col3" >-0.481165</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row3_col4" class="data row3 col4" >0.850229</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row4" class="row_heading level0 row4" >4</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col0" class="data row4 col0" >5</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col1" class="data row4 col1" >1.45342</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col2" class="data row4 col2" >1.05774</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col3" class="data row4 col3" >0.165562</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row4_col4" class="data row4 col4" >0.515018</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row5" class="row_heading level0 row5" >5</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row5_col0" class="data row5 col0" >6</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row5_col1" class="data row5 col1" >-1.33694</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row5_col2" class="data row5 col2" >0.562861</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row5_col3" class="data row5 col3" >1.39285</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row5_col4" class="data row5 col4" >-0.063328</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row6" class="row_heading level0 row6" >6</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col0" class="data row6 col0" >7</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col1" class="data row6 col1" >0.121668</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col2" class="data row6 col2" >1.2076</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col3" class="data row6 col3" >-0.00204021</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row6_col4" class="data row6 col4" >1.6278</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row7" class="row_heading level0 row7" >7</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col0" class="data row7 col0" >8</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col1" class="data row7 col1" >0.354493</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col2" class="data row7 col2" >1.03753</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col3" class="data row7 col3" >-0.385684</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row7_col4" class="data row7 col4" >0.519818</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row8" class="row_heading level0 row8" >8</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col0" class="data row8 col0" >9</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col1" class="data row8 col1" >1.68658</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col2" class="data row8 col2" >-1.32596</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col3" class="data row8 col3" >1.42898</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row8_col4" class="data row8 col4" >-2.08935</td>
</tr> <tr>
<th id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3level0_row9" class="row_heading level0 row9" >9</th>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row9_col0" class="data row9 col0" >10</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row9_col1" class="data row9 col1" >-0.12982</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row9_col2" class="data row9 col2" >0.631523</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row9_col3" class="data row9 col3" >-0.586538</td>
<td id="T_0189b640_cb1a_11e8_b68b_c8d3ffd26fc3row9_col4" class="data row9 col4" >0.29072</td>
</tr></tbody>
</table>

Pandas dataframe.to_html() - add background color to header

You can try doing this in two ways:

With set_table_styles from pandas.DataFrame.style:

import pandas as pd
import numpy as np

# Set up a DataFrame
np.random.seed(24)
df = pd.DataFrame({'A': np.linspace(1, 10, 10)})
df = pd.concat([df, pd.DataFrame(np.random.randn(10, 4), columns=list('BCDE'))],
axis=1)
df.iloc[0, 2] = np.nan

df_html_output = df.style.set_table_styles(
[{'selector': 'thead th',
'props': [('background-color', 'red')]},
{'selector': 'thead th:first-child',
'props': [('display','none')]},
{'selector': 'tbody th:first-child',
'props': [('display','none')]}]
).render()

html.append(df_html_output)
body = '\r\n\n<br>'.join('%s'%item for item in html)
msg.attach(MIMEText(body, 'html'))

Or with .to_html:

df_html_output = df.to_html(na_rep = "", index = False).replace('<th>','<th style = "background-color: red">')

html.append(df_html_output)
body = '\r\n\n<br>'.join('%s'%item for item in html)
msg.attach(MIMEText(body, 'html'))

The second one provides the option of removing the index column during the export (to_html) without having to do too much HTML tweaking; so it may be more suited to your needs.

I hope this proves useful.

Changing the back ground color of rows in a dataframe using python styling

So, once you solve the str/int comparison, with something like int(row['parking_space'][:2]), it looks like this has been solved in this question.

Using a not-accepted answer from that question:

def highlight(row):
if int(row.parking_space[:2]) <= 25:
return ['background-color: green']*3
elif int(row.parking_space[:2]) >=26 and int(row.parking_space[:2]) <=50:
return ['background-color:yellow']*3
else:
return ['background-color:red']*3

Then, to save the styled dataframe, you assign a variable as below

df_styled=df.style.apply(highlight, axis=1)

df_styled is now a <pandas.io.formats.style.Styler objectthat generates a string of self-contained CSS and HTML.

If you then call df_styler.render() you get the HTML ready to be saved as plaintext and rendered by a browser:

<style  type="text/css" >
#T_20b96880_c80e_11e8_a82d_a0afbd198380row0_col0 {
background-color: yellow;
...

Apply CSS class to Pandas DataFrame using to_html

Pandas' to_html simply outputs a large string containing HTML table markup. The classes argument is a convenience handler to give the <table> a class attribute that will be referenced in a previously created CSS document that styles it. Therefore, incorporate to_html into a wider HTML document build that references an external CSS.

Interestingly, to_html adds dual classes <table class="dataframe mystyle"> which can be referenced in CSS individually, .dataframe {...} .mystyle{...}, or together .dataframe.mystyle {...}. Below demonstrates with random data.

Data

import pandas as pd
import numpy as np

pd.set_option('display.width', 1000)
pd.set_option('colheader_justify', 'center')

np.random.seed(6182018)
demo_df = pd.DataFrame({'date': np.random.choice(pd.date_range('2018-01-01', '2018-06-18', freq='D'), 50),
'analysis_tool': np.random.choice(['pandas', 'r', 'julia', 'sas', 'stata', 'spss'],50),
'database': np.random.choice(['postgres', 'mysql', 'sqlite', 'oracle', 'sql server', 'db2'],50),
'os': np.random.choice(['windows 10', 'ubuntu', 'mac os', 'android', 'ios', 'windows 7', 'debian'],50),
'num1': np.random.randn(50)*100,
'num2': np.random.uniform(0,1,50),
'num3': np.random.randint(100, size=50),
'bool': np.random.choice([True, False], 50)
},
columns=['date', 'analysis_tool', 'num1', 'database', 'num2', 'os', 'num3', 'bool']
)

print(demo_df.head(10))
# date analysis_tool num1 database num2 os num3 bool
# 0 2018-04-21 pandas 153.474246 mysql 0.658533 ios 74 True
# 1 2018-04-13 sas 199.461669 sqlite 0.656985 windows 7 11 False
# 2 2018-06-09 stata 12.918608 oracle 0.495707 android 25 False
# 3 2018-04-24 spss 88.562111 sql server 0.113580 windows 7 42 False
# 4 2018-05-05 spss 110.231277 oracle 0.660977 windows 10 76 True
# 5 2018-04-05 sas -68.140295 sql server 0.346894 windows 10 0 True
# 6 2018-05-07 julia 12.874660 postgres 0.195217 ios 79 True
# 7 2018-01-22 r 189.410928 mysql 0.234815 windows 10 56 False
# 8 2018-01-12 pandas -111.412564 sql server 0.580253 debian 30 False
# 9 2018-04-12 r 38.963967 postgres 0.266604 windows 7 46 False

CSS (save as df_style.css)

/* includes alternating gray and white with on-hover color */

.mystyle {
font-size: 11pt;
font-family: Arial;
border-collapse: collapse;
border: 1px solid silver;

}

.mystyle td, th {
padding: 5px;
}

.mystyle tr:nth-child(even) {
background: #E0E0E0;
}

.mystyle tr:hover {
background: silver;
cursor: pointer;
}

Pandas

pd.set_option('colheader_justify', 'center')   # FOR TABLE <th>

html_string = '''
<html>
<head><title>HTML Pandas Dataframe with CSS</title></head>
<link rel="stylesheet" type="text/css" href="df_style.css"/>
<body>
{table}
</body>
</html>.
'''

# OUTPUT AN HTML FILE
with open('myhtml.html', 'w') as f:
f.write(html_string.format(table=demo_df.to_html(classes='mystyle')))

OUTPUT

HTML (references df_style.css, assumed in same directory; see class argument in table)

<html>
<head><title>HTML Pandas Dataframe with CSS</title></head>
<link rel="stylesheet" type="text/css" href="df_style.css"/>
<body>
<table border="1" class="dataframe mystyle">
<thead>
<tr style="text-align: center;">
<th></th>
<th>date</th>
<th>analysis_tool</th>
<th>num1</th>
<th>database</th>
<th>num2</th>
<th>os</th>
<th>num3</th>
<th>bool</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>2018-04-21</td>
<td>pandas</td>
<td>153.474246</td>
<td>mysql</td>
<td>0.658533</td>
<td>ios</td>
<td>74</td>
<td>True</td>
</tr>
<tr>
<th>1</th>
<td>2018-04-13</td>
<td>sas</td>
<td>199.461669</td>
<td>sqlite</td>
<td>0.656985</td>
<td>windows 7</td>
<td>11</td>
<td>False</td>
</tr>
<tr>
<th>2</th>
<td>2018-06-09</td>
<td>stata</td>
<td>12.918608</td>
<td>oracle</td>
<td>0.495707</td>
<td>android</td>
<td>25</td>
<td>False</td>
</tr>
<tr>
<th>3</th>
<td>2018-04-24</td>
<td>spss</td>
<td>88.562111</td>
<td>sql server</td>
<td>0.113580</td>
<td>windows 7</td>
<td>42</td>
<td>False</td>
</tr>
<tr>
<th>4</th>
<td>2018-05-05</td>
<td>spss</td>
<td>110.231277</td>
<td>oracle</td>
<td>0.660977</td>
<td>windows 10</td>
<td>76</td>
<td>True</td>
</tr>
...
</tbody>
</table>
</body>
</html>

HTML Output



Related Topics



Leave a reply



Submit