I have a DataFrame
:
0 1
0 3.000 5.600
1 1.200 3.456
and for presentation purposes I would like it to be converted to
0 1
0 3 5.6
1 1.2 3.456
What is the elegant way to achieve this (without looping inefficiently over entries of the DataFrame
)?
Or perhaps more generally: is there a way to set pandas
up such that it is always doing this? E.g. one of the pandas
options?
Notice that pd.options.display.float_format = '{:,.0f}'.format
will not work, as it would give a fixed number of decimals, rather than having it vary across entries of the DataFrame
as I indicated above.
In [188]: df
Out[188]:
a b c
0 1.0000 2.2460 2.0000
1 3.0000 4.4920 6.0000
2 5.0000 6.7380 10.0000
In [189]: pd.options.display.float_format = '{:,.2f}'.format
In [190]: df.apply(lambda x: x.astype(int) if np.allclose(x, x.astype(int)) else x)
Out[190]:
a b c
0 1 2.25 2
1 3 4.49 6
2 5 6.74 10
UPDATE:
In [222]: df
Out[222]:
0 1
0 3.0000 5.6000
1 1.2000 3.4560
In [223]: df.applymap(lambda x: str(int(x)) if abs(x - int(x)) < 1e-6 else str(round(x,2)))
Out[223]:
0 1
0 3 5.6
1 1.2 3.46
NOTE: be aware that .applymap() method is pretty slow as it's doing map(func, series)
for each series in the DataFrame
a simple method using round(), pass the number of digits you want to round to as a parameter.
Assuming that your DataFrame is named 'df':
df.round(2)
output:
0 1
0 3.00 5.60
1 1.20 3.45
A good solution for this to test whether the value has a decimal part and format it accordingly :
pd.options.display.float_format = lambda x : '{:.0f}'.format(x) if int(x) == x else '{:,.2f}'.format(x)
Edit: This will produce an error when NaNs are in your data. Consider instead using round():
pd.options.display.float_format = lambda x : '{:.0f}'.format(x) if round(x,0) == x else '{:,.2f}'.format(x)