0

I want to apply some styles to whole row and I am doing like this.

df = pd.DataFrame({
    'correlation':[0.5, 0.1,0.9],
    "volume": [38,45,10]})

def highlight_col(x):
    #copy df to new - original data are not changed
    df = x.copy()
    #set by condition
    mask = df['volume'] <= 40
    df.loc[mask, :] = 'background-color: yellow'
    df.loc[~mask,:] = 'background-color: ""'
    return df    

df.style.apply(highlight_col, axis=None)

But I see that nothing happens. Can somebody guide me in the right direction please?

PS: I believe it should call ´highlight_col´ function but it wont.

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
stafan
  • 155
  • 1
  • 9
  • In my environment, lines 0 and 2 have a yellow background. – r-beginners Oct 05 '20 at 13:48
  • Change your line `df.style.apply(highlight_col, axis=None)` as `df = df.style.apply(highlight_col, axis=None)`. You need to overwrite the dataframe, or save it in another variable (as you prefer), because your function return a dataframe that is not the original one, but a copy, so your changes are not on the original df but on the copy. Pay attention to ser the bg color as `'background-color: ""'`, this is an Unhandled format, so it will produce a black background – Carlo Zanocco Oct 05 '20 at 14:19
  • @r-beginners wow. I tried in two environment, it did not highlight for me. Wondering whats missing !!! – stafan Oct 05 '20 at 14:52
  • @CarloZanocco You are wrong unfortunately. It will store style object in df if you assign it. – stafan Oct 05 '20 at 14:53
  • @stafan Please take a look to my answer, It should work also for you, anyway let me know if it works. – Carlo Zanocco Oct 05 '20 at 16:12

1 Answers1

2

Take a look to the styling guide provided by pandas.

The function df.style.apply() return a Styler object, so your dataframe don't contain the styiling but you need to save the output of the apply function and use to_excel() on this output. In your code I have done it directly without saving.

I made some tests editing your code, take a look:

import pandas as pd

df = pd.DataFrame({
    'correlation':[0.5, 0.1,0.9],
    "volume": [38,45,10]})

def highlight_col(x):
    #copy df to new - original data are not changed
    df = x.copy()
    #set by condition
    mask = df['volume'] <= 40

    df.loc[mask, :] = "background-color: yellow"
    df.loc[~mask,:] = ''

    return df    

df.style.apply(highlight_col, axis=None).to_excel('test.xlsx')

This produce the following output:

out1

Setting the color to: df.loc[~mask,:] = "background-color: ''" generate a warning: CSSWarning: Unhandled color format: "''" and set the color to black, that could be solved changing the line as df.loc[~mask,:] = ''. This will produce:

out2

In the case you really want the black row, is better to specify it with "background-color: black".

You can also change the line df.style.apply(highlight_col, axis=None).to_excel('test.xlsx') with:

s = df.style.apply(highlight_col, axis=None)
s.to_excel('test.xlsx')

It will produce the same output:

out2


To get the Styler as HTML format you can simply use the render() function and print the output:

s = df.style.apply(highlight_col, axis=None)
print(s.render())

You can also use _repr_html_:

s = df.style.apply(highlight_col, axis=None)
print(s._repr_html_())

Output:

<style  type="text/css" >
    #T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow0_col0 {
            background-color:  yellow;
        }    #T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow0_col1 {
            background-color:  yellow;
        }    #T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow1_col0 {
            background-color:  black;
        }    #T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow1_col1 {
            background-color:  black;
        }    #T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow2_col0 {
            background-color:  yellow;
        }    #T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow2_col1 {
            background-color:  yellow;
        }</style><table id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0f" ><thead>    <tr>        <th class="blank level0" ></th>        <th class="col_heading level0 col0" >correlation</th>        <th class="col_heading level0 col1" >volume</th>    </tr></thead><tbody>
                <tr>
                        <th id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0flevel0_row0" class="row_heading level0 row0" >0</th>
                        <td id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow0_col0" class="data row0 col0" >0.5</td>
                        <td id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow0_col1" class="data row0 col1" >38</td>
            </tr>
            <tr>
                        <th id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0flevel0_row1" class="row_heading level0 row1" >1</th>
                        <td id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow1_col0" class="data row1 col0" >0.1</td>
                        <td id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow1_col1" class="data row1 col1" >45</td>
            </tr>
            <tr>
                        <th id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0flevel0_row2" class="row_heading level0 row2" >2</th>
                        <td id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow2_col0" class="data row2 col0" >0.9</td>
                        <td id="T_c4d4737f_0729_11eb_9637_dcfb48aafb0frow2_col1" class="data row2 col1" >10</td>
            </tr>
    </tbody></table>

In the case you want to change the style only for the cell and not for the row, take a look to this possible solution:

import pandas as pd

df = pd.DataFrame({
    'correlation':[0.5, 0.1,0.9],
    "volume": [38,45,10]})

def highlight_col(x):
    if(x.name == 'volume'):
        mask = x <= 40
        return ['background-color: yellow' if v else '' for v in mask]
    return [''] * len(x)

df.style.apply(highlight_col).to_excel('test.xlsx')

Output:

output

Carlo Zanocco
  • 1,967
  • 4
  • 18
  • 31