Home > Blockchain >  Pandas Styler and float_format
Pandas Styler and float_format

Time:03-18

Consider the example:

import pandas as pd

pd.options.display.float_format = '{:,.3f}'.format

df = pd.DataFrame.from_dict(dict(name=['a', 'b', 'c'], value=[1.1234,2.123332,3.232433]))
print(df)

df = df.style.apply(lambda x: ['background: lightgreen' if (x.name == 1) else '' for i in x], axis=1)
print(df.to_html())

HTML output:

<style type="text/css">
#T_fa0b6_row1_col0, #T_fa0b6_row1_col1 {
  background: lightgreen;
}
</style>
<table id="T_fa0b6">
  <thead>
    <tr>
      <th  >&nbsp;</th>
      <th id="T_fa0b6_level0_col0"  >name</th>
      <th id="T_fa0b6_level0_col1"  >value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th id="T_fa0b6_level0_row0"  >0</th>
      <td id="T_fa0b6_row0_col0"  >a</td>
      <td id="T_fa0b6_row0_col1"  >1.123400</td>
    </tr>
    <tr>
      <th id="T_fa0b6_level0_row1"  >1</th>
      <td id="T_fa0b6_row1_col0"  >b</td>
      <td id="T_fa0b6_row1_col1"  >2.123332</td>
    </tr>
    <tr>
      <th id="T_fa0b6_level0_row2"  >2</th>
      <td id="T_fa0b6_row2_col0"  >c</td>
      <td id="T_fa0b6_row2_col1"  >3.232433</td>
    </tr>
  </tbody>
</table>

When I apply a style to a row, I notice it invalidates the float_format precision that has been applied. When I dump to HTML, I see 6 digits after the decimal instead of the three. What is the correct way to fix this?

I'm creating a dataframe that has a row called 'Total'. I would like this row to be highlighted only. I dump this to a HTML, and then run weasyprint to generate a PDF. I will have a lot of tables in my PDF. Maybe it is better to create a special CSS class that performs this styling, but how do I assign a CSS class to one row in a dataframe only?

CodePudding user response:

It seems like the styler's output is different from the rest of pandas output, so I guess it doesn't respect pd.options. Instead, you can use the format method of Styler objects.

You can either specify the precision directly:

style = df.style.apply(lambda x: ['background: lightgreen' if (x.name == 1) else '' for i in x], axis=1)
style = style.format(precision=3)

Or, specify a custom formatter:

formatter = {
    'value': '{:,.3f}'.format  # same as lambda x: '{:,.3f}'.format(x)
}
style = style.format(formatter=formatter)

Output:

>>> print(style.to_html())
<style type="text/css">
#T_95068_row1_col0, #T_95068_row1_col1 {
  background: lightgreen;
}
</style>
<table id="T_95068_">
  <thead>
    <tr>
      <th  >&nbsp;</th>
      <th  >name</th>
      <th  >value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th id="T_95068_level0_row0"  >0</th>
      <td id="T_95068_row0_col0"  >a</td>
      <td id="T_95068_row0_col1"  >1.123</td>
    </tr>
    <tr>
      <th id="T_95068_level0_row1"  >1</th>
      <td id="T_95068_row1_col0"  >b</td>
      <td id="T_95068_row1_col1"  >2.123</td>
    </tr>
    <tr>
      <th id="T_95068_level0_row2"  >2</th>
      <td id="T_95068_row2_col0"  >c</td>
      <td id="T_95068_row2_col1"  >3.232</td>
    </tr>
  </tbody>
</table>

Note the 3-digit precision in the above.

  • Related