Pandas to_dict 意外修改浮点数
Posted
技术标签:
【中文标题】Pandas to_dict 意外修改浮点数【英文标题】:Pandas to_dict unwantedly modifying float numbers 【发布时间】:2016-08-10 06:32:19 【问题描述】:我下面的代码接收 CSV 数据并使用 pandas to_dict()
函数作为将数据转换为 JSON 的一个步骤。 问题在于修改浮点数(例如 1.6 变为 1.6000000000000001)。我不担心准确性的损失,但因为用户会看到数字的变化,所以看起来很业余。 p>
我知道:
这是在here 之前提出的问题,但这是两年前的事了,并没有得到很好的回答, 还有一个复杂的问题:我希望转换为字典的数据帧可以是数据类型的任意组合因此,以前的解决方案的问题是:
-
仅当您不需要(在数字上)使用数字时,才能将所有数字转换为对象。我想要计算总和和平均值的选项,这会重新引入加法小数问题。
强制将数字四舍五入到小数点后 x 会降低准确性或添加额外的不必要的 0,具体取决于用户提供的数据
我的问题:
有没有更好的方法来确保数字不会被修改,而是保存在数字数据类型中?是否首先要更改我导入 CSV 数据的方式?当然有一个我忽略的简单解决方案?
这里有一个简单的脚本可以重现这个错误:
import pandas as pd
import sys
if sys.version_info[0] < 3:
from StringIO import StringIO
else:
from io import StringIO
CSV_Data = "Index,Column_1,Column_2,Column_3,Column_4,Column_5,Column_6,Column_7,Column_8\nindex_1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8\nindex_2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8\nindex_3,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.8\nindex_4,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8"
input_data = StringIO(CSV_Data)
df = pd.DataFrame.from_csv(path = input_data, header = 0, sep=',', index_col=0, encoding='utf-8')
print(df.to_dict(orient = 'records'))
【问题讨论】:
如果最终目标是使用 json,为什么不使用df.to_json(orient = 'records')
?
@JohnGalt 基本上,为了允许列的动态嵌套,我使用 to_dict 创建的字典被插入到我正在构建的更大字典中,最后被转储到 JSON。
你可以使用pd.io.json.dumps(nested_dicts_with_pd_objects)
,这对你有用吗?理想情况下,不应该引入舍入场景。
我可能会误解您的答案,但导致问题的不是“转储到 JSON”部分,而是字典的创建。除非有办法直接在 Python 中构建 JSON 对象?
在字典中,数值可以用扩展小数显示,当你使用pd.io.json.dumps(nested_dicts_with_pd_objects)
时,用户不会看到扩展小数。您可能想添加详细示例?
【参考方案1】:
您可以使用 pd.io.json.dumps
处理带有 pandas 对象的嵌套字典。
让我们创建一个带有数据框记录和自定义指标的summary
dict。
In [137]: summary = 'df': df.to_dict(orient = 'records'), 'df_metric': df.sum() / df.min()
In [138]: summary['df_metric']
Out[138]:
Column_1 9.454545
Column_2 9.000000
Column_3 8.615385
Column_4 8.285714
Column_5 8.000000
Column_6 7.750000
Column_7 7.529412
Column_8 7.333333
dtype: float64
In [139]: pd.io.json.dumps(summary)
Out[139]: '"df":["Column_7":1.7,"Column_6":1.6,"Column_5":1.5,"Column_4":1.4,"Column_3":1.3,"Column_2":1.2,"Column_1":1.1,"Column_8":1.8,"Column_7":2.7,"Column_6":2.6,"Column_5":2.5,"Column_4":2.4,"Column_3":2.3,"Column_2":2.2,"Column_1":2.1,"Column_8":2.8,"Column_7":3.7,"Column_6":3.6,"Column_5":3.5,"Column_4":3.4,"Column_3":3.3,"Column_2":3.2,"Column_1":3.1,"Column_8":3.8,"Column_7":4.7,"Column_6":4.6,"Column_5":4.5,"Column_4":4.4,"Column_3":4.3,"Column_2":4.2,"Column_1":4.1,"Column_8":4.8],"df_metric":"Column_1":9.4545454545,"Column_2":9.0,"Column_3":8.6153846154,"Column_4":8.2857142857,"Column_5":8.0,"Column_6":7.75,"Column_7":7.5294117647,"Column_8":7.3333333333'
使用 double_precision
更改双精度数的最大数字精度。
注意。 df_metric
值。
In [140]: pd.io.json.dumps(summary, double_precision=2)
Out[140]: '"df":["Column_7":1.7,"Column_6":1.6,"Column_5":1.5,"Column_4":1.4,"Column_3":1.3,"Column_2":1.2,"Column_1":1.1,"Column_8":1.8,"Column_7":2.7,"Column_6":2.6,"Column_5":2.5,"Column_4":2.4,"Column_3":2.3,"Column_2":2.2,"Column_1":2.1,"Column_8":2.8,"Column_7":3.7,"Column_6":3.6,"Column_5":3.5,"Column_4":3.4,"Column_3":3.3,"Column_2":3.2,"Column_1":3.1,"Column_8":3.8,"Column_7":4.7,"Column_6":4.6,"Column_5":4.5,"Column_4":4.4,"Column_3":4.3,"Column_2":4.2,"Column_1":4.1,"Column_8":4.8],"df_metric":"Column_1":9.45,"Column_2":9.0,"Column_3":8.62,"Column_4":8.29,"Column_5":8.0,"Column_6":7.75,"Column_7":7.53,"Column_8":7.33'
您可以使用orient='records/index/..'
来处理数据帧 -> to_json 构造。
In [144]: pd.io.json.dumps(summary, orient='records')
Out[144]: '"df":["Column_7":1.7,"Column_6":1.6,"Column_5":1.5,"Column_4":1.4,"Column_3":1.3,"Column_2":1.2,"Column_1":1.1,"Column_8":1.8,"Column_7":2.7,"Column_6":2.6,"Column_5":2.5,"Column_4":2.4,"Column_3":2.3,"Column_2":2.2,"Column_1":2.1,"Column_8":2.8,"Column_7":3.7,"Column_6":3.6,"Column_5":3.5,"Column_4":3.4,"Column_3":3.3,"Column_2":3.2,"Column_1":3.1,"Column_8":3.8,"Column_7":4.7,"Column_6":4.6,"Column_5":4.5,"Column_4":4.4,"Column_3":4.3,"Column_2":4.2,"Column_1":4.1,"Column_8":4.8],"df_metric":[9.4545454545,9.0,8.6153846154,8.2857142857,8.0,7.75,7.5294117647,7.3333333333]'
本质上,pd.io.json.dumps
- 将任意对象递归转换为 JSON,内部使用 ultrajson
【讨论】:
【参考方案2】:我需要用正确的浮点数制作df.to_dict('list')
。但是df.to_json()
还不支持orient='list'
。所以我做了以下事情:
list_oriented_dict =
column: list(data.values())
for column, data in json.loads(df.to_json()).items()
不是最好的方法,但它对我有用。也许有人有更优雅的解决方案?
【讨论】:
以上是关于Pandas to_dict 意外修改浮点数的主要内容,如果未能解决你的问题,请参考以下文章
pandas multiindex DataFrame中的圆形浮点数
pandas创建内容全是0的dataframepandas基于随机整数随机浮点数创建dataframe(random numbers)