【问题标题】:pandas to_sql postgresql with array dtypes带有数组 dtypes 的 pandas to_sql postgresql
【发布时间】:2021-12-14 05:42:38
【问题描述】:

我有一个数据框,其中包含日期时间值和数组以及将来可能的其他数据类型。 我希望将它 to_sql 到 PostgreSQL,其中 datetime 是(没有时区的时间戳)并且数组是(字节)类型,但我不知道为 dtype 参数放什么。

有没有办法根据数据框列的数据类型动态地执行数据类型?

表格的外观:

CREATE TABLE IF NOT EXISTS data2_mcw_tmp (
      time timestamp without time zone,
      u bytea,
      v bytea,
      w bytea,
      spd bytea,
      dir bytea,
      temp bytea
);

到目前为止我的代码(在用户 rftr 的帮助下):

dtypedict = {}
Data2_mcw_conv = Data2_mcw.copy()

for row in Data2_mcw_conv.index:
  for col in Data2_mcw_conv.columns:

    value = Data2_mcw_conv[col][row]

    try:
      if type(Data2_mcw_conv[col].iloc[0]).__module__ == np.__name__:

        dtypedict.update({col:BYTEA})

        value = Data2_mcw_conv[col].loc[row]

        print('before: ')
        print (value.flags)
        print('---------------------')
          
        value = value.copy(order='C')

        print('after: ')
        print (value.flags)
        print('=====================')
          
        value = pickle.dumps(value)

    except:    
      if isinstance(Data2_mcw_conv[col].iloc[0], datetime.date):

        dtypedict.update({col:TIMESTAMP})
        
    Data2_mcw_conv[col][row] = value

Data2_mcw_conv.to_sql(name='data2_mcw_tmp',con=conn, 
                    if_exists = 'replace',
                    dtype=dtypedict)

但是,我收到此错误:

Traceback (most recent call last):
  File "C:\Users\myname\Desktop\database\pickletopdb2.py", line 145, in <module>
    postgres_conv()
  File "C:\Users\myname\Desktop\database\pickletopdb2.py", line 124, in postgres_conv
    Data2_mcw_conv.to_sql(name='data2_mcw_tmp',con=conn,
  File "C:\Python38\lib\site-packages\pandas\core\generic.py", line 2778, in to_sql
    sql.to_sql(
  File "C:\Python38\lib\site-packages\pandas\io\sql.py", line 590, in to_sql
    pandas_sql.to_sql(
  File "C:\Python38\lib\site-packages\pandas\io\sql.py", line 1397, in to_sql
    table.insert(chunksize, method=method)
  File "C:\Python38\lib\site-packages\pandas\io\sql.py", line 831, in insert
    exec_insert(conn, keys, chunk_iter)
  File "C:\Python38\lib\site-packages\pandas\io\sql.py", line 748, in _execute_insert
    conn.execute(self.table.insert(), data)
  File "C:\Python38\lib\site-packages\sqlalchemy\engine\base.py", line 1286, in execute
    return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
  File "C:\Python38\lib\site-packages\sqlalchemy\sql\elements.py", line 325, in _execute_on_connection
    return connection._execute_clauseelement(
  File "C:\Python38\lib\site-packages\sqlalchemy\engine\base.py", line 1478, in _execute_clauseelement
    ret = self._execute_context(
  File "C:\Python38\lib\site-packages\sqlalchemy\engine\base.py", line 1842, in _execute_context
    self._handle_dbapi_exception(
  File "C:\Python38\lib\site-packages\sqlalchemy\engine\base.py", line 2027, in _handle_dbapi_exception
    util.raise_(exc_info[1], with_traceback=exc_info[2])
  File "C:\Python38\lib\site-packages\sqlalchemy\util\compat.py", line 207, in raise_
    raise exception
  File "C:\Python38\lib\site-packages\sqlalchemy\engine\base.py", line 1779, in _execute_context
    self.dialect.do_executemany(
  File "C:\Python38\lib\site-packages\sqlalchemy\dialects\postgresql\psycopg2.py", line 951, in do_executemany
    context._psycopg2_fetched_rows = xtras.execute_values(
  File "C:\Python38\lib\site-packages\psycopg2\extras.py", line 1267, in execute_values
    parts.append(cur.mogrify(template, args))
ValueError: ndarray is not C-contiguous

value.flag 在 value = value.copy(order='C') 之前/之后输出:

before: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

---------------------
after: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

=====================

为什么会出现这个错误以及如何解决它?

【问题讨论】:

    标签: python pandas postgresql dataframe pandas-to-sql


    【解决方案1】:

    按照this answer 的第二个代码sn-p 并将dtypes 自定义为here 中的PostgreSQL 等效项。所以在你的情况下,例如:

    from sqlalchemy.dialects.postgresql import BYTEA, TIMESTAMP
    
    def sqlcol(dfparam):
        # ...
        if "datetime" in str(j):
            dtypedict.update({i: TIMESTAMP})
        if "object" in str(j):  # Depending on what your other column's datatypes are
            dtypesdict.update({i: BYTEA})
        # ...
    

    注意事项:

    • 根据docsTIMESTAMP默认没有时区。
    • 您的(字节)列通常用pandas 中的数据类型object 表示。如果您以后添加更多数据,您应该考虑到这一点。

    【讨论】:

    • 感谢您的提示,我听取了您的建议并取得了一些进展,但是当我尝试将数组移植到其中时遇到错误,我已将错误和当前代码添加到我的原始问题中
    • 您的数组的顺序似乎与C 不同。因此,在将数组添加到生成的数据帧之前,请尝试使用 arr = arr.copy(order='C') 转换它们,而 arr 是您各自的数组。
    • 您好,感谢您的建议!我刚试过,但它仍然给出同样的错误。它与我做数组的pickle.dump有什么关系吗?我需要这样做,因为 BYTEA 是二进制数据的数据类型,而不是数组,并且没有其他方法可以将 numpy 数组放入我所知道的 postgresql 数据库中。
    • 请在value = value(order='C') 行之后用print(value.flags) 显示结果吗?
    • 我在value=value(order='C") 行之前/之后添加了输出
    猜你喜欢
    • 2020-08-09
    • 2017-10-12
    • 2021-09-29
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 2015-09-01
    • 1970-01-01
    相关资源
    最近更新 更多