python - 具有 NUMERIC(10,2) 等参数化数据类型的 Pandas to_sql

标签 python postgresql pandas sqlalchemy

Pandas 有一个可爱的 to_sql 方法,用于将数据帧写入 SQLAlchemy 支持的任何 RDBMS。

假设我有一个这样生成的数据框:

df = pd.DataFrame([-1.04, 0.70, 0.11, -0.43, 1.0], columns=['value'])

如果我尝试在没有任何特殊行为的情况下将其写入数据库,我会得到一个 double 列类型:

df.to_sql('foo_test', an_engine)

如果我想要不同的数据类型,我可以指定它(这很好用):

df.to_sql('foo_test', an_engine, dtype={'value': sqlalchemy.types.NUMERIC})

但是如果我想设置NUMERIC 列的精度和小数位数,它会在我面前爆炸:

df.to_sql('foo_test', an_engine, dtype={'value': sqlalchemy.types.NUMERIC(10,2)})


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-77-dc008463fbfc> in <module>()
      1 df = pd.DataFrame([-1.04, 0.70, 0.11, -0.43, 1.0], columns=['value'])
----> 2 df.to_sql('foo_test', cosd_engine, dtype={'value': sqlalchemy.types.NUMERIC(10,2)})

/Users/igazit/.virtualenvs/myproject/lib/python2.7/site-packages/pandas/core/generic.pyc in to_sql(self, name, con, flavor, schema, if_exists, index, index_label, chunksize, dtype)
    964             self, name, con, flavor=flavor, schema=schema, if_exists=if_exists,
    965             index=index, index_label=index_label, chunksize=chunksize,
--> 966             dtype=dtype)
    967 
    968     def to_pickle(self, path):

/Users/igazit/.virtualenvs/myproject/lib/python2.7/site-packages/pandas/io/sql.pyc in to_sql(frame, name, con, flavor, schema, if_exists, index, index_label, chunksize, dtype)
    536     pandas_sql.to_sql(frame, name, if_exists=if_exists, index=index,
    537                       index_label=index_label, schema=schema,
--> 538                       chunksize=chunksize, dtype=dtype)
    539 
    540 

/Users/igazit/.virtualenvs/myproject/lib/python2.7/site-packages/pandas/io/sql.pyc in to_sql(self, frame, name, if_exists, index, index_label, schema, chunksize, dtype)
   1162             import sqlalchemy.sql.type_api as type_api
   1163             for col, my_type in dtype.items():
-> 1164                 if not issubclass(my_type, type_api.TypeEngine):
   1165                     raise ValueError('The type of %s is not a SQLAlchemy '
   1166                                      'type ' % col)

TypeError: issubclass() arg 1 must be a class

我试图深入了解为什么 sqlalchemy.types.NUMERIC 的类型在 1164 上通过了测试,而 sqlalchemy.types.NUMERIC(10,2)没有。它们确实有不同的类型(sqlalchemy.sql.visitors.VisitableTypesqlalchemy.sql.sqltypes.NUMERIC)。

任何线索将不胜感激!

最佳答案

更新:此错误已针对 pandas >= 0.16.0 修复


这是一篇关于最近的 pandas bug 的帖子,它与 0.15.2 有同样的错误。

https://github.com/pydata/pandas/issues/9083

合作者建议使用 to_sql 猴子补丁作为解决问题的方法

from pandas.io.sql import SQLTable

def to_sql(self, frame, name, if_exists='fail', index=True,
           index_label=None, schema=None, chunksize=None, dtype=None):
    """
    patched version of https://github.com/pydata/pandas/blob/v0.15.2/pandas/io/sql.py#L1129
    """
    if dtype is not None:
        from sqlalchemy.types import to_instance, TypeEngine
        for col, my_type in dtype.items():
            if not isinstance(to_instance(my_type), TypeEngine):
                raise ValueError('The type of %s is not a SQLAlchemy '
                                 'type ' % col)

    table = SQLTable(name, self, frame=frame, index=index,
                     if_exists=if_exists, index_label=index_label,
                     schema=schema, dtype=dtype)
    table.create()
    table.insert(chunksize)
    # check for potentially case sensitivity issues (GH7815)
    if name not in self.engine.table_names(schema=schema or self.meta.schema):
        warnings.warn("The provided table name '{0}' is not found exactly "
                      "as such in the database after writing the table, "
                      "possibly due to case sensitivity issues. Consider "
                      "using lower case table names.".format(name), UserWarning)

pd.io.sql.SQLDatabase.to_sql = to_sql

关于python - 具有 NUMERIC(10,2) 等参数化数据类型的 Pandas to_sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27766283/

相关文章:

python - scrapy-selenium 驱动程序不遵循

python - 套接字 "import"不工作 "from"可以!这是怎么回事?

postgresql - Sequelizejs 模式同步不返回

arrays - 将 HSTORE 数组值转换为 JSONB 中的列

pandas - 标准化 Pandas 数据框中的一列

python - Spark 读取二进制文件的子组

python - virtualenv 和 python 中的两个版本的 OpenCV

node.js - Typeorm 给我 QueryFailedError : column reference "id" is ambiguous

python - 使用 Pandas 数据框和嵌套在 Python 中的循环的基于项目的协作过滤器的瓶颈

python - 有效地将不均匀的列表列表转换为用 nan 填充的最小包含数组