【问题标题】:pandas read sql db2 corrupts decimal熊猫读取 sql db2 损坏十进制
【发布时间】:2018-10-03 05:13:34
【问题描述】:

我正在尝试使用 db2 读取数据表。然而,似乎小数被简单地忽略了,浮点数以某种方式乘以100。例如,100.50 在读入 pandas 数据帧时变为10050.0

顺便说一句,我来自挪威,所以小数点用, 而不是. 表示。我不知道这是否重要。

我使用以下 SQL(在 WinSQL Lite 中):

SELECT CUSTOMER_ID, FUND_NAME, SAVINGS_AMOUNT
FROM SAVINGS_TABLE
WHERE CUSTOMER_ID = 1

,给出:

CUSTOMER_ID, FUND_NAME, SAVINGS_AMOUNT
          1    ASSET_X       259131,72
          1    ASSET_Y       718533,33   

我知道这是正确的,所以问题不在于数据。

在 Spyder 中,使用 Python,我有

import pandas as pd
import pyodbc as po

DSN = 'MY_DSN'
UID = 'MY_USER'
PWD = 'MY_PASSWORD'
CON = po.connect('DSN={0}; UID={1}; PWD={2}'.format(DSN, UID, PWD))

SQL = """SELECT CUSTOMER_ID, FUND_NAME, SAVINGS_AMOUNT
FROM SAVINGS_TABLE
WHERE CUSTOMER_ID = 1"""

df = pd.read_sql(SQL, CON)

df
Out[16]: 
    CUSTOMER_ID    FUND_NAME    SAVINGS_AMOUNT
0             1      ASSET_X        25913172.0
1             1      ASSET_Y        71853333.0

这里发生了什么,我该如何解决?

SAVINGS_AMOUNT 列是 DECIMALSize=9Scale=2。当然,这个问题与此有关。我想我必须在pd.read_sql 中设置一个参数来解释该列。

我知道我可以简单地除以 100 来纠正这个问题。但我不想那样做。我想读正确的数字。

我也在使用 Windows。

【问题讨论】:

    标签: python sql pandas


    【解决方案1】:

    不确定您是否尝试过强制 SQL 输入:

    SQL = """SELECT CUSTOMER_ID, FUND_NAME, Cast(SAVINGS_AMOUNT AS Decimal(20,2))
    FROM SAVINGS_TABLE
    WHERE CUSTOMER_ID = 1"""
    

    【讨论】:

    • 您好,抱歉回复晚了。这可能有效。问题是我必须知道数据存储的格式。相关的数据库中有一堆表,不同的表使用不同的精度。
    【解决方案2】:

    您可能会发现将小数点分隔符显式设置为挪威使用的分隔符会有所帮助

    pyodbc.setDecimalSeparator(',')
    

    【讨论】:

    • 谢谢。我会试试看。
    【解决方案3】:

    请试试这个。它可能会起作用。

    import numpy as np
    np.round(p_table, decimals=2)
    

    【讨论】:

    • 嗨,谢谢。我知道如何通过编码来“解决”这个问题。我不想这样做。因为这要求我知道基础数据的精度。我工作的数据库有数百个表和数千个列,精度不同,我不想跟踪所有这些,
    【解决方案4】:

    read_csv 中可以指定小数点分隔符,但在read_sql 中不能这样做。您的语言环境可能设置不正确。在read_sql 之前,试试这个:

    import locale
    locale.set_locale(locale.LC_NUMERIC, "no_NO")
    

    或者,如果这不起作用,您可以尝试将有问题的列转换为 SQL 查询中的字符串,然后执行 .replace 将逗号转换为句点,最后将其转换回数字.这不需要您事先知道精度。

    【讨论】:

    • 嗨,谢谢。似乎 Python 没有响应 set_locale 而是 setlocale。出于某种原因,我得到了Error: unsupported locale setting。我会看看我能不能让它工作。
    • 在 Windows 中它似乎是 locale.setlocale(locale.LC_NUMERIC, "no")
    【解决方案5】:

    你试过设置pd.read_sql(SQL, CON, coerce_float=false)吗?这可能是尝试将小数更改为浮点数的问题。

    https://pandas.pydata.org/pandas-docs/version/0.20/generated/pandas.read_sql.html

    编辑:

    如果这不起作用,您可以尝试在 SQL 中将 int 转换为字符串,然后在 Python 中将逗号替换为小数并转换为 float。一个相当耗费资源的答案,但它可以完成工作。

    【讨论】:

    • 嗨。谢谢你的建议。这似乎将整个事情转换为 int,但它仍然没有给出正确的答案。 IE。如果答案是 123.45,则为 12345。:(
    • 嗯.. 我唯一能做的就是将所有内容都转换为 sql 中的字符串,然后在 Python 中,用小数替换逗号,然后转换为浮点数。这将是一个代价高昂的过程,但可能会产生预期的结果。
    • 嗨,转换为字符串然后再转换回浮点数实际上是可行的。我不得不写“选择 varchar(SAVINGS_AMOUNT) ...”。它并不漂亮,但它是唯一不需要我事先知道精度的建议解决方案。如果你修改你的答案,我会检查它是否“正确”。
    • @mortysporty 可能不漂亮,但我很高兴它有效!
    • 同意!谢谢。
    猜你喜欢
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 2016-10-31
    • 2022-06-22
    • 1970-01-01
    • 2013-08-11
    相关资源
    最近更新 更多