Description
Currently there are ways of performing a to_json()
method with the desired output formatting but the procedure is a bit cumbersome:
df = pd.DataFrame(data=[[1.9999, 1.9999, 1.9999, 1.9999, 1.99]], columns=['A', 'B', 'C', 'D', 'E'])
df['A'] = df['A'].apply(lambda x: float(f'{x:,.00f}'))
df['B'] = df['B'].apply(lambda x: int(f'{x:,.00f}'))
df['C'] = df['C'].apply(lambda x: f'{x:,.01f}')
print(df.to_json(double_precision=3))
{"A":{"0":2.0},
"B":{"0":2},
"C":{"0":"2.0"},
"D":{"0":2.0},
"E":{"0":1.99}}
The Styler
has its own formatter which can make things a little more aesthetic, and has the advantage of not affecting the underlying data:
df = pd.DataFrame(data=[[1.9999, 1.9999, 1.9999, 1.9999, 1.99]], columns=['A', 'B', 'C', 'D', 'E'])
print(Styler(df, uuid="", precision=3).format({
'A': lambda x: float(f'{x:,.00f}'),
'B': lambda x: int(f'{x:,.00f}'),
'C': '{:,.01f}'.format
}).render())
<tr>
<th id="T_7e7fd_level0_row0" class="row_heading level0 row0" >0</th>
<td id="T_7e7fd_row0_col0" class="data row0 col0" >2.0</td>
<td id="T_7e7fd_row0_col1" class="data row0 col1" >2</td>
<td id="T_7e7fd_row0_col2" class="data row0 col2" >2.0</td>
<td id="T_7e7fd_row0_col3" class="data row0 col3" >2.000</td>
<td id="T_7e7fd_row0_col4" class="data row0 col4" >1.990</td>
</tr>
But Styler does not have a to_json()
method.
Describe the solution you'd like
I would like to add a simple extension to the Styler to create JSON from the formatted Styler Object, in a similar way as it constructs HTML tables:
class Styler:
...
def to_json(self, **kwargs):
"""
Applies the ``:meth:DataFrame.to_json`` method to the ``Styler`` object
including existing formats.
Parameters
----------
**kwargs
Any additional keyword arguments are passed to ``DataFrame.to_json()``.
Useful to control the output structure of the JSON return.
Returns
-------
None or str
Examples
--------
>>> df = pd.DataFrame(data=[[1.9999, 1.9999, 1.9999, 1.9999, 1.99]],
columns=['A', 'B', 'C', 'D', 'E'])
>>> df.style.format({
... 'A': lambda x: float(f'{x:,.00f}'),
... 'B': lambda x: int(f'{x:,.00f}'),
... 'C': '{:,.01f}'.format
... }).to_json()
{"A":{"0":2.0},"B":{"0":2.0},"C":{"0":"2.0"},"D":{"0":"1.999900"}}
"""
df = self.data.copy()
for r in range(len(df.index)):
for c in range(len(df.columns)):
formatter = self._display_funcs[(r, c)]
df.iloc[r, c] = formatter(self.data.iloc[r, c])
return df.to_json(**kwargs)
API breaking implications
None - new feature
Might be useful to make some minor adjustments to Styler factory default formatter, but this is optional and can happen later.
Describe alternatives you've considered
- Building a formatter for a DataFrame without using styler and applying
to_json
to that. - Adding a
formatter
argument toDataFrame.to_json
which performs the necessary adjustments before
Since Styler is inherently a 'display' context component and specifically designed for the web I thought it more suitable to add to_json
to the Styler
object.
Opinions welcome.. I will probably submit a PR if consensus approval..