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 读取的 sql 整数变为浮点数

pandas multiindex DataFrame中的圆形浮点数

将日期转换为浮点数以对 Pandas 数据框进行线性回归

将 pandas 数据框列标签从浮点数转换为整数

使用带有浮点数的 pandas reindex:插值

pandas创建内容全是0的dataframepandas基于随机整数随机浮点数创建dataframe(random numbers)