Output different precision by column with pandas.DataFrame.to_csv()?

Question:

Question

Is it possible to specify a float precision specifically for each column to be printed by the Python pandas package method pandas.DataFrame.to_csv?

Background

If I have a pandas dataframe that is arranged like this:

In [53]: df_data[:5]
Out[53]: 
    year  month  day       lats       lons  vals
0   2012      6   16  81.862745 -29.834254   0.0
1   2012      6   16  81.862745 -29.502762   0.1
2   2012      6   16  81.862745 -29.171271   0.0
3   2012      6   16  81.862745 -28.839779   0.2
4   2012      6   16  81.862745 -28.508287   0.0

There is the float_format option that can be used to specify a precision, but this applys that precision to all columns of the dataframe when printed.

When I use that like so:

df_data.to_csv(outfile, index=False,
                   header=False, float_format='%11.6f')

I get the following, where vals is given an inaccurate precision:

2012,6,16,  81.862745, -29.834254,   0.000000
2012,6,16,  81.862745, -29.502762,   0.100000
2012,6,16,  81.862745, -29.171270,   0.000000
2012,6,16,  81.862745, -28.839779,   0.200000
2012,6,16,  81.862745, -28.508287,   0.000000
Asked By: ryanjdillon

||

Answers:

Change the type of column “vals” prior to exporting the data frame to a CSV file

df_data['vals'] = df_data['vals'].map(lambda x: '%2.1f' % x)

df_data.to_csv(outfile, index=False, header=False, float_format='%11.6f')
Answered By: hknust

You can do this with to_string. There is a formatters argument where you can provide a dict of columns names to formatters. Then you can use some regexp to replace the default column separators with your delimiter of choice.

Answered By: mattexx

The more current version of hknust’s first line would be:

df_data['vals'] = df_data['vals'].map(lambda x: '{0:.1}'.format(x))

To print without scientific notation:

df_data['vals'] = df_data['vals'].map(lambda x: '{0:.1f}'.format(x)) 
Answered By: Michael Szczepaniak

The to_string approach suggested by @mattexx looks better to me, since it doesn’t modify the dataframe.

It also generalizes well when using jupyter notebooks to get pretty HTML output, via the to_html method. Here we set a new default precision of 4, and override it to get 5 digits for a particular column wider:

from IPython.display import HTML
from IPython.display import display

pd.set_option('precision', 4)

display(HTML(df.to_html(formatters={'wider': '{:,.5f}'.format})))
Answered By: nealmcb

You can use round method for dataframe before saving the dataframe to the file.

df_data = df_data.round(6)
df_data.to_csv('myfile.dat')
Answered By: Peaceful

This question is a bit old, but I’d like to contribute with a better answer, I think so:

formats = {'lats': '{:10.5f}', 'lons': '{:.3E}', 'vals': '{:2.1f}'}

for col, f in formats.items():
    df_data[col] = df_data[col].map(lambda x: f.format(x))

I tried with the solution here, but it didn’t work for me, I decided to experiment with previus solutions given here combined with that from the link above.

Answered By: Nacho