如何使用 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 中加入 2 列词嵌入

在 Pandas 数据框中加载大表时,如何避免 EC2 中的内存错误?

如何在 Python 中的一个常规 Pandas DataFrame 中加入许多零散的时间序列

在 pandas 中加入数据帧时的内存问题(时间索引)

使用数据框在 Pandas 中加载 csv 文件

pandas 是不是读取完整的数据文件并将其存储在数据框中?在 pandas 中加载 100mb 文件是不是有效?