如何使用 Pandas 在 MySQL-DB 中加载和保存部分表
Posted
技术标签:
【中文标题】如何使用 Pandas 在 MySQL-DB 中加载和保存部分表【英文标题】:How to load and save partial table in a MySQL-DB with Pandas 【发布时间】:2017-10-19 18:27:11 【问题描述】:熊猫新手。
一个 SQL 表由 3 列组成(ID 是主键):
> ID VALUE1 VALUE2
> 1 11 28
> 2 21 (None)
> 3 31 56
> 4 41 (None)
使用 Pandas,我加载了 VALUE2 为 (None) 的所有行:
query = "SELECT * FROM `TABLE_NAME` WHERE (`VALUE2` IS NULL)"
engine = create_engine("mysql://user:pwd@ip/db"
df = pd.read_sql(query, con=engine)
engine.dispose()
到目前为止一切正常。
在加载后,缺失的 VALUE2 会根据一些规则进行计算。
问题
如果我用
更新数据库df.to_sql(TABLE_NAME, con=engine, if_exists="replace", index=False)
所有未加载到数据框中的原始行都丢失了:
> ID VALUE1 VALUE2
> 2 21 103
> 4 41 72
有没有办法更新而不影响原始行?
我想得到这个:
> ID VALUE1 VALUE2
> 1 11 28
> 2 21 103
> 3 31 56
> 4 41 72
看起来整个表被重写而不是更新......
仅仅为了更新几行而加载整个表是非常低效的。这实际上可以解决问题,但这是不可接受的。
对“为什么”有任何想法吗?
【问题讨论】:
【参考方案1】:这是一个混合两个世界的最佳案例。做你现在正在做的事情,但使用不同的桌子。这本质上是一个临时表,但 AFAIK pandas 不支持它们,所以让我们稍后将其删除。
df.to_sql(tmp_table_name, con=engine, if_exists="replace", index=False)
然后我们使用INSERT ON DUPLICATE KEY 语法
INSERT INTO TABLE_NAME (SELECT * FROM tmp_table) ON DUPLICATE KEY UPDATE a = VALUES(a), b=VALUES(b) ....
这通常是一个快速的操作。
【讨论】:
对于这么“简单”的事情,竟然要经过双重步骤,这有点奇怪。 Pandas 非常接近独自完成这项工作......谢谢! 很高兴能帮上忙【参考方案2】:您正在使用选项if_exists="replace"
。
来自 Pandas 文档(我的胆子):
replace:如果表存在,删除它,重新创建它,然后插入数据。
所以它完全按照你的要求做。您可以尝试改用if_exists="append"
,但它仍然可能无法提供您想要的行为。
或者,您可以直接使用 MySQLdb 与您的表进行交互,并使用UPDATE。
【讨论】:
看起来我误解了“替换”:忽略文档,我认为它是指单个记录,而不是整个表。谢谢。以上是关于如何使用 Pandas 在 MySQL-DB 中加载和保存部分表的主要内容,如果未能解决你的问题,请参考以下文章
在 Pandas 数据框中加载大表时,如何避免 EC2 中的内存错误?