使用 pandas.DataFrame.to_csv() 按列输出不同的精度?
Posted
技术标签:
【中文标题】使用 pandas.DataFrame.to_csv() 按列输出不同的精度?【英文标题】:Output different precision by column with pandas.DataFrame.to_csv()? 【发布时间】:2013-11-28 23:26:27 【问题描述】:问题
是否可以为 Python pandas
封装方法 pandas.DataFrame.to_csv 打印的每一列专门指定一个浮点精度?
背景
如果我有一个像这样排列的pandas
数据框:
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
float_format
选项可用于指定精度,但这会在打印时将该精度应用于数据帧的所有列。
当我这样使用时:
df_data.to_csv(outfile, index=False,
header=False, float_format='%11.6f')
我得到以下信息,其中vals
的精度不准确:
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
【问题讨论】:
【参考方案1】:在将数据框导出到 CSV 文件之前更改列“vals”的类型
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')
【讨论】:
请注意,您不仅要更改 val 的类型,还要对其进行四舍五入。如果修改列不可接受,则可以在执行 to_csv() 写入时将其保存到临时列“vals.numeric”。 这设置了数字,但它将我列中的所有空白都变成了“nan”,这也通过 to_csv 进入了 csv,我无法摆脱它。跨度> 为了避免nan问题,我的方法是lambda x: '%2.1f % x if not pd.isna(x) else ''
【参考方案2】:
hknust 第一行的更新版本是:
df_data['vals'] = df_data['vals'].map(lambda x: '0:.1'.format(x))
不使用科学计数法打印:
df_data['vals'] = df_data['vals'].map(lambda x: '0:.1f'.format(x))
【讨论】:
这样做的问题是值变成了字符串【参考方案3】:在将数据框保存到文件之前,您可以对数据框使用round 方法。
df_data = df_data.round(6)
df_data.to_csv('myfile.dat')
【讨论】:
【参考方案4】:这个问题有点老了,但我想贡献一个更好的答案,我想是的:
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))
我尝试了here 的解决方案,但它对我不起作用,我决定尝试这里给出的以前的解决方案以及上面链接中的解决方案。
【讨论】:
您发布的链接是用于生成的 CSS 以显示在 Jupyter 笔记本中,因此如果您希望生成的 CSV 格式无效,那么这将不起作用。您选择的答案将所有列转换为(格式化的)字符串数据类型。对于格式字符串,首选的 Python3.6+ 方式现在是f"x:2.1f"
而不是 "%2.1f" % x
。
现在我解决了这个问题。谢谢@ryanjdillon【参考方案5】:
您可以使用to_string
执行此操作。有一个 formatters
参数,您可以在其中向格式化程序提供列名的字典。然后,您可以使用一些正则表达式将默认的列分隔符替换为您选择的分隔符。
【讨论】:
这似乎也是一个好方法。我想知道什么更有效。谢谢! 我还没有测试过哪个效率更高,但我不得不猜测这个,因为它不会修改数据框... 嗨@matlexx 如果你能详细说明一下就好了。.to_string()
方法只是将 df 转换为我最后的一个连接字符串。我看不出如何将其输出发送到.to_csv()
@NikhilVJ 我认为.to_string()
应该能够做到.to_csv()
所做的一切。
@MilindR 再次阅读您的评论,我发现我错误地解释了您的陈述......无论哪种方式,如果 to_csv 方法可以使用格式化程序会很好。【参考方案6】:
@mattexx 建议的 to_string
方法对我来说看起来更好,因为它不会修改数据框。
当使用jupyter
笔记本通过to_html
方法获得漂亮的HTML 输出时,它也可以很好地泛化。在这里,我们设置了一个新的默认精度 4,并覆盖它以获取特定列 wider
的 5 位数字:
from IPython.display import HTML
from IPython.display import display
pd.set_option('precision', 4)
display(HTML(df.to_html(formatters='wider': ':,.5f'.format)))
【讨论】:
我喜欢这个想法,并且同意你的论点,但是formatters
参数不适用于df.to_csv
函数...
@Géraud 谢谢。太糟糕了——也许你可以提出问题?但也许他们认为,为了像 csv 这样的文件导出而对数据进行四舍五入就没那么有意义了,并且有很多方法可以以表格格式显示 csv 文件,并使用它们自己的可定制方式来确定精度。以上是关于使用 pandas.DataFrame.to_csv() 按列输出不同的精度?的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)