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.
enter image description here

Asked By: Chenyang

||

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) 

enter image description here

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) 

enter image description here

Answered By: MagnusO_O

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:

df normal


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" >&nbsp;</th>
      <th id="T_d7719_level0_col0" class="col_heading level0 col0" >col1</th>
      ...
    </tr>
  </thead>

Notice: <th class="blank level0" >&nbsp;</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:

df normal


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:

df cell with col name
df cell with index name
df cell with both col name and index


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')]
     }]
)

df cell both col index name differently colored

Answered By: ouroboros1
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.