【问题标题】:How to avoid duplicates on copying data from Python pandas dataframe to SQL database SQLLite?如何避免将数据从 Python pandas 数据框复制到 SQL 数据库 SQLite 时出现重复?
【发布时间】:2020-06-16 19:16:37
【问题描述】:

我想将 pandas 数据框插入到我使用 SQL alchemy 预先创建的 sqltable 中。

但是,这样做我会得到重复,因为 SQLite 有一个索引列,当我从数据框中复制时,它会采用不同的索引,即使数据相同,它也可能会附加它。

关于我的状态的详细信息:

我的 pandas 数据框在插入时没有索引。 (index=False) 即使索引是主键,重要的是剩余数据。数据行不得重复,例如每列具有相同的内容组合。

My SQL alchemy 创建表:(来自 database.py)

class SQLTable(Base):
    __tablename__ = 'sqltable'
    __table_args__ = {'sqlite_autoincrement': True}
    index = Column(Integer, primary_key= True, nullable=False)
    A = Column(Integer, nullable=True)
    B  = Column(String, nullable=True)
    C  = Column(BigInteger, nullable=True)
    D  = Column(Integer, nullable=True)
    E  = Column(String, nullable=True)
    F  = Column(Float, nullable=True)

但是,如果索引以外的行不存在,我只希望插入到 sqltable 中。 我找到了python-pandas-tosql-only-insert-new-rows,但我不知道如何将其应用于我的数据。

 df.to_sql(
     name="sqltable", 
     con=engine,
     if_exists='replace',
     index=False,
     dtype={
         'index': sqlalchemy.types.INTEGER(),
         'A': sqlalchemy.types.INTEGER(),
         'B': sqlalchemy.types.VARCHAR(length=255),
         'C': sqlalchemy.types.BIGINT(),
         'D': sqlalchemy.types.VARCHAR(length=255),
         'E': sqlalchemy.types.VARCHAR(length=255),
         'F': sqlalchemy.types.Float(precision=3, asdecimal=True)
     }
 )  

如何进行索引? 最好的方法是什么?

向 SQL 表插入新行的在线教程

【问题讨论】:

  • 你试过没有 table_args = {'sqlite_autoincrement': True} 吗?它会总是自动增加您的索引请参阅:stackoverflow.com/questions/4567574/…。我认为这不是您想要的行为。
  • 您的笑脸数据有多大?就我个人而言,我会使用存储过程并使用哈希函数来仅引入增量,但我认为您不能在 SQL 中使用存储过程?将在下面添加熊猫解决方案

标签: python python-3.x pandas sqlite pandasql


【解决方案1】:

将熊猫行作为占位符写入不同的表。

import pandas as pd

col_options = dict(
    dtype={
        'index': sqlalchemy.types.INTEGER(),
        'A': sqlalchemy.types.INTEGER(),
        'B': sqlalchemy.types.VARCHAR(length=255),
        'C': sqlalchemy.types.BIGINT(),
        'D': sqlalchemy.types.VARCHAR(length=255),
        'E': sqlalchemy.types.VARCHAR(length=255),
        'F': sqlalchemy.types.Float(precision=3, asdecimal=True)
    }
)
df.to_sql(name="sqltable_temp", con=engine, if_exists='replace', index=False, **col_options)  

在将占位符表中的值与您打算写入新记录的表中的值进行比较时,仅检索新记录。

query = """
    SELECT A, B, C, D, E, F FROM sqltable_temp 
    EXCEPT 
    SELECT A, B, C, D, E, F FROM sqltable;
"""

new_entries = pd.read_sql(query, con=engine, **col_options)

在表中追加新记录。

new_entries.to_sql(
    name="sqltable", con=engine, if_exists='append', **col_options)

最后,删除占位符表

engine.execute("DROP TABLE sqltable_temp;")

【讨论】:

  • 当我将鼠标悬停在 pd 上的 new_entries = pd.read_sql(query, **db_options) 上时,函数 callpylint(unexpected-keyword-arg) 中出现意外的关键字参数 'dtype',似乎有错误。即使我添加 DROP TABLE sqltable_temp,sqltable_temp 也不会被删除;我能做些什么?我使用 Visual Studio 代码编辑器。似乎从 new_entries 上看没有什么东西,而且代码也没有从在线的新条目中执行。你能帮帮我吗?
  • 感谢您指出这些错误。 dtypes 不是 DataFrame.read_sql 的有效选项。取出con选项字典,单独传递
  • 也可以用索引来完成,因为它仍然没有处理和跳过行吗??
  • 代码停在 pd.read_sql 并且没有被执行。你能帮帮我吗?
  • 并非没有更好的信息。你怎么确定它在跳线?是否引发了异常?也许,当sqltable_tempsqltable 比较时,没有新条目。您可以打印new_entries 以查看它是否为空数据框。
猜你喜欢
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多