How to style upper left cell of a Pandas DataFrame
Question:
I understand to access the top left cell of a dataframe we need to use df.columns.name
and I can see the pandas document on styling provides example to style row/column headers with apply_index
(https://pandas.pydata.org/docs/user_guide/style.html)
The question I have is how to style this top left cell, say color it blue. Thanks.
import pandas as pd
d = {'col1': [1, 2], 'col2': [3, 4]}
df = pd.DataFrame(data=d)
df.columns.name = 'Test'
df
Update: ouroboros1’s answer below is very informative and helpful. But seems like when converting the Styler object to Excel, i.e. to_excel(), the format to the top left cell is not preserved.
In the documentation (and in Export to Excel section), it is stated that "Table level styles, and data cell CSS-classes are not included in the export to Excel: individual cells must have their properties mapped by the Styler.apply
and/or Styler.applymap
methods".
Update: Thanks to @ouroboros1
Here is a possible solution for anyone who is interested.
d = {'col1': [1, 2], 'col2': [3, 4]}
color_matrix_df = pd.DataFrame([['background-color:yellow', 'background-color:yellow'],
['background-color:yellow', 'background-color:blue']])
df = pd.DataFrame(data=d)
df.columns.name = 'Test'
df
def colors(df, color_matrix_df):
style_df = pd.DataFrame(color_matrix_df.values, index=df.index, columns=df.columns)
return style_df.applymap(lambda elem: elem)
df_upper_left_cell = df.style.set_table_styles(
[{'selector': '.index_name',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}]
)
df_upper_left_cell.apply(colors, axis=None, color_matrix_df=color_matrix_df)
w = pd.ExcelWriter('Test.xlsx', engine='xlsxwriter')
df_upper_left_cell.to_excel(w, index=True)
wb = w.book
ws = w.sheets['Sheet1']
fmt_header = wb.add_format({'fg_color': '#cd5c5c', 'align': 'center'})
ws.write(0,0, df_upper_left_cell.data.columns.name, fmt_header)
w.save()
The above code will color the dataframe as shown below and saved the same to the Excel file.
Answers:
Based on The Coding Bot: How to colour a specific cell in pandas dataframe based on its position?
You can use style.apply
together with an iloc
for that specific cell to assign a color.
def styling_specific_cell(x,row_idx,col_idx):
#color = 'background-color: lightblue; color: blue'
#color = 'color: blue'
color = 'background-color: lightblue'
df_styler = pd.DataFrame('', index=x.index, columns=x.columns)
df_styler.iloc[row_idx, col_idx] = color
return df_styler
style_idx_row = 0
style_idx_column = 0
df.style.apply(styling_specific_cell, row_idx = style_idx_row, col_idx = style_idx_column,
axis = None)
Change the #
within the function for font color or both.
To see the steps within the function check:
print(pd.DataFrame('', index=df.index, columns=df.columns))
print(df.iloc[0,0])
To assing a color to a specific index you can use style.applymap_index
:
def color_b(v):
return "background-color: lightblue;" if v == 0 else None
df.style.applymap_index(color_b)
You can use Styler.set_table_styles
for this.
We have the following options:
- Top left corner (hereafter: "cell") is empty (no
name
set)
- cell contains either
df.columns.name
or df.index.name
, or both
Grouped there are three options to style cell (entirely, or partially). I’ll walk through them below. First the data:
import pandas as pd
df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
df
Standard look:
Option 1. Cell is empty
Trick is to look at the output for print(df.style.set_table_styles().to_html())
:
<thead>
<tr>
<th class="blank level0" > </th>
<th id="T_d7719_level0_col0" class="col_heading level0 col0" >col1</th>
...
</tr>
</thead>
Notice: <th class="blank level0" > </th>
. We can access these class names and set the format. E.g. in this case, we access blank
(level0
applying to all of level0
, i.e. all cols and index too).
df.style.set_table_styles(
[{'selector': '.blank',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}]
)
Result:
Option 2. Either df.columns.name
or df.index.name
, or both. One style to entire cell.
In either scenario, we will need .index_name
instead of .blank
. E.g.
df.columns.name = 'columns'
df.style.set_table_styles(
[{'selector': '.index_name',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}]
)
Result:
Option 3. df.columns.name
and df.index.name
, different styles.
This one is a little more tricky, as we will need to add tr:nth-child(1)
for columns.name
and tr:nth-child(2)
for index.name
.
# just setting col and index name immediately inside `pd.DataFrame`
df = pd.DataFrame([[1,3],[2,4]],
columns=pd.Index(['col1','col2'], name='columns'),
index=pd.Index([0,1], name='index'))
df.style.set_table_styles(
[{'selector': 'tr:nth-child(1) .index_name',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}, {'selector': 'tr:nth-child(2) .index_name',
'props': [('background-color', '#EECACA'),
('color', 'black')]
}]
)
I understand to access the top left cell of a dataframe we need to use df.columns.name
and I can see the pandas document on styling provides example to style row/column headers with apply_index
(https://pandas.pydata.org/docs/user_guide/style.html)
The question I have is how to style this top left cell, say color it blue. Thanks.
import pandas as pd
d = {'col1': [1, 2], 'col2': [3, 4]}
df = pd.DataFrame(data=d)
df.columns.name = 'Test'
df
Update: ouroboros1’s answer below is very informative and helpful. But seems like when converting the Styler object to Excel, i.e. to_excel(), the format to the top left cell is not preserved.
In the documentation (and in Export to Excel section), it is stated that "Table level styles, and data cell CSS-classes are not included in the export to Excel: individual cells must have their properties mapped by the Styler.apply
and/or Styler.applymap
methods".
Update: Thanks to @ouroboros1
Here is a possible solution for anyone who is interested.
d = {'col1': [1, 2], 'col2': [3, 4]}
color_matrix_df = pd.DataFrame([['background-color:yellow', 'background-color:yellow'],
['background-color:yellow', 'background-color:blue']])
df = pd.DataFrame(data=d)
df.columns.name = 'Test'
df
def colors(df, color_matrix_df):
style_df = pd.DataFrame(color_matrix_df.values, index=df.index, columns=df.columns)
return style_df.applymap(lambda elem: elem)
df_upper_left_cell = df.style.set_table_styles(
[{'selector': '.index_name',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}]
)
df_upper_left_cell.apply(colors, axis=None, color_matrix_df=color_matrix_df)
w = pd.ExcelWriter('Test.xlsx', engine='xlsxwriter')
df_upper_left_cell.to_excel(w, index=True)
wb = w.book
ws = w.sheets['Sheet1']
fmt_header = wb.add_format({'fg_color': '#cd5c5c', 'align': 'center'})
ws.write(0,0, df_upper_left_cell.data.columns.name, fmt_header)
w.save()
The above code will color the dataframe as shown below and saved the same to the Excel file.
Based on The Coding Bot: How to colour a specific cell in pandas dataframe based on its position?
You can use style.apply
together with an iloc
for that specific cell to assign a color.
def styling_specific_cell(x,row_idx,col_idx):
#color = 'background-color: lightblue; color: blue'
#color = 'color: blue'
color = 'background-color: lightblue'
df_styler = pd.DataFrame('', index=x.index, columns=x.columns)
df_styler.iloc[row_idx, col_idx] = color
return df_styler
style_idx_row = 0
style_idx_column = 0
df.style.apply(styling_specific_cell, row_idx = style_idx_row, col_idx = style_idx_column,
axis = None)
Change the #
within the function for font color or both.
To see the steps within the function check:
print(pd.DataFrame('', index=df.index, columns=df.columns))
print(df.iloc[0,0])
To assing a color to a specific index you can use style.applymap_index
:
def color_b(v):
return "background-color: lightblue;" if v == 0 else None
df.style.applymap_index(color_b)
You can use Styler.set_table_styles
for this.
We have the following options:
- Top left corner (hereafter: "cell") is empty (no
name
set) - cell contains either
df.columns.name
ordf.index.name
, or both
Grouped there are three options to style cell (entirely, or partially). I’ll walk through them below. First the data:
import pandas as pd
df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
df
Standard look:
Option 1. Cell is empty
Trick is to look at the output for print(df.style.set_table_styles().to_html())
:
<thead>
<tr>
<th class="blank level0" > </th>
<th id="T_d7719_level0_col0" class="col_heading level0 col0" >col1</th>
...
</tr>
</thead>
Notice: <th class="blank level0" > </th>
. We can access these class names and set the format. E.g. in this case, we access blank
(level0
applying to all of level0
, i.e. all cols and index too).
df.style.set_table_styles(
[{'selector': '.blank',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}]
)
Result:
Option 2. Either df.columns.name
or df.index.name
, or both. One style to entire cell.
In either scenario, we will need .index_name
instead of .blank
. E.g.
df.columns.name = 'columns'
df.style.set_table_styles(
[{'selector': '.index_name',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}]
)
Result:
Option 3. df.columns.name
and df.index.name
, different styles.
This one is a little more tricky, as we will need to add tr:nth-child(1)
for columns.name
and tr:nth-child(2)
for index.name
.
# just setting col and index name immediately inside `pd.DataFrame`
df = pd.DataFrame([[1,3],[2,4]],
columns=pd.Index(['col1','col2'], name='columns'),
index=pd.Index([0,1], name='index'))
df.style.set_table_styles(
[{'selector': 'tr:nth-child(1) .index_name',
'props': [('background-color', 'IndianRed'),
('color', 'white')]
}, {'selector': 'tr:nth-child(2) .index_name',
'props': [('background-color', '#EECACA'),
('color', 'black')]
}]
)