【问题标题】:Looping trough dataframe and checking rows before appending to database在附加到数据库之前循环遍历数据框并检查行
【发布时间】:2020-09-15 03:48:22
【问题描述】:

问题如何将我的数据框附加到数据库,以便它检查 stock_ticker 是否存在,仅附加 stock_ticker 不存在的行?

这是我做的过程

  1. 将 CSV 文件导入 pandas 数据框
  2. 将列名指定为与数据库中的相同
  3. 使用以下代码将数据帧发送到数据库,但获取

sqlite3.IntegrityError: UNIQUE constraint failed: stocks.stock_ticker

conn = sqlite3.connect('stockmarket.db')
c = conn.cursor()

df.to_sql(name='stocks', con=conn, if_exists='append', index=False)

conn.commit()

我查看了其他完整性错误案例,但似乎找不到适用于附加数据帧的案例?我找到并尝试了这个,但它所做的只是不附加任何内容。

try:
    conn = sqlite3.connect('stockmarket.db')
    c = conn.cursor()
    df.to_sql(name='stocks', con=conn, if_exists='append', index=False)
    conn.commit()
except sqlite3.IntegrityError:
    print("Already in database")

我不确定我是否正确理解了迭代的东西

How to iterate over rows in a DataFrame in Pandas

所以我尝试了这个,但它只是在数据库中为每个人打印出来。更难的是,有 4 个新的股票代码。

for index, row in df.iterrows():
    try:
        conn = sqlite3.connect('stockmarket.db')
        c = conn.cursor()
        df.to_sql(name='stocks', con=conn, if_exists='append', index=False)
        conn.commit()
    except sqlite3.IntegrityError:
        print("Already in database")

数据库看起来像这样

任何见解都非常感谢:)

【问题讨论】:

    标签: python pandas sqlite dataframe finance


    【解决方案1】:

    看起来发生这种情况是因为 Pandas 不允许声明正确的 ON CONFLICT 策略,以防您尝试将数据附加到具有相同(唯一)主键或违反其他一些 UNIQUEness 约束的表中。 if_exists 仅指整个本身,而不是每一行。

    我想你已经想出了一个很好的答案,也许稍微修改一下它就会对你有用:

    # After connecting
    for i in range(len(df)):
        try:
            df[df.index == i].to_sql(name='stocks', con=conn, if_exists='append', index=False)
            conn.commit()
        except sqlite3.IntegrityError:
            pass
    

    现在,如果您想在 Pandas 数据中出现新值时实际替换该值,并且假设您想替换数据库中的旧值,这可能是一个问题。在这种情况下,您可能希望将原始 SQL 命令用作字符串,并迭代地传递 Pandas 值。例如:

    insert_statement = """
    INSERT INTO stocks (stock_id,
                        stock_ticker,
                        {other columns})
    VALUES (%s, %s, {as many %s as columns})
    ON CONFLICT (stock_id) DO UPDATE
        SET {Define which values you will update on conflict}"""
    

    然后你可以运行

    for i in range(len(df)):
        values = tuple(df.iloc[i])
        cursor.execute(insert_statement, values)
    

    【讨论】:

    • 感谢您抽出宝贵时间帮助我:)。我尝试了第一个代码,我在原始问题中进行了编辑以显示它的外观和我得到的错误。我添加正确了吗?对于您建议的第二部分。我设置了所有列名,但是我将 %s 更改为什么?也不确定我是否也改变了集合中的点......抱歉,新手问题>.
    • @Jakub 我刚刚编辑了我的回复来解决这个问题。看来如果你拿df.iloc[i],Pandas 不知道如何将这个系列发送到数据库(因此table stocks has no column named 0)。我在第一个块中更改了该行。关于第二个,具体的语法实际上取决于数据库。例如在 Postgres 中,语法是这样的:postgresqltutorial.com/postgresql-upsert 最后,%s 只是一个字符串格式化的符号,见这里:stackoverflow.com/questions/902408/…
    • 非常感谢您的帮助!您的编辑解决了我的问题:),现在尝试从链接中找出如何执行您添加的第二部分。在你指出之前我什至没有意识到这一点。是的,我需要能够使用新信息更新 stock_tickers 的行,如果它们已经存在,则无需添加新的 stock_tickers >.
    猜你喜欢
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    相关资源
    最近更新 更多