我尝试查询MySql数据库表的子集,将结果输入Pandas DataFrame,修改一些数据,然后将更新的行写回到同一个表中。(〈50,000),因此返回整个表并执行df.to_sql(tablename,engine, if_exists='replace')
不是一个可行的选择。是否有一种直接的方法可以UPDATE已更改的行,而无需遍历DataFrame中的每一行?
我知道这个项目,它试图模拟一个“upsert”工作流,但似乎它只完成了插入新的非重复行的任务,而不是更新现有行的一部分:
GitHub Pandas-to_sql-upsert
以下是我试图在更大范围内实现的目标的框架:
import pandas as pd
from sqlalchemy import create_engine
import threading
#Get sample data
d = {'A' : [1, 2, 3, 4], 'B' : [4, 3, 2, 1]}
df = pd.DataFrame(d)
engine = create_engine(SQLALCHEMY_DATABASE_URI)
#Create a table with a unique constraint on A.
engine.execute("""DROP TABLE IF EXISTS test_upsert """)
engine.execute("""CREATE TABLE test_upsert (
A INTEGER,
B INTEGER,
PRIMARY KEY (A))
""")
#Insert data using pandas.to_sql
df.to_sql('test_upsert', engine, if_exists='append', index=False)
#Alter row where 'A' == 2
df_in_db.loc[df_in_db['A'] == 2, 'B'] = 6
现在,我想将df_in_db
写回到'test_upsert'
表中,并反映更新后的数据。
这个SO问题非常相似,其中一条评论建议使用一个“sqlalchemy表类”来执行任务。
Update table using sqlalchemy table class
如果这是实现它的最佳(唯一?)方式,有人能扩展一下我将如何为我上面的特定情况实现它吗?
4条答案
按热度按时间2ic8powd1#
我认为最简单的方法是:
首先删除那些将要被“upserted”的行,这可以在一个循环中完成,但是对于更大的数据集(5K+行)来说效率不是很高,所以我将DF的这个切片保存到一个临时的MySQL表中:
PS我没有测试这个代码,所以它可能有一些小错误,但它应该给予你一个想法...
oxalkeyp2#
使用Panda's to_sql“方法”参数和sqlalchemy的mysql insert on_duplicate_key_update特性的MySQL特定解决方案:
wgx48brx3#
我之前一直在挣扎现在我找到了办法。
基本上就是创建一个单独的数据框,在其中保存只需更新的数据。
现在将
s_update
传递给cursor.execute
或engine.execute
(无论您在何处执行SQL查询)这将立即更新您的数据。
tf7tbtn24#
下面是一个通用函数,它将更新每一行(但同时更新行中的所有值)