开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

使用 SQLAlchemy 将 pandas DataFrame 导出到 SQLite

在执行探索性数据分析时,例如在使用 pandas 检查 COVID-19 数据时,从 CSV、XML 或 JSON 等文件加载到 apandas DataFrame 中是很常见的。然后,您可以对 DataFrame 中的数据进行一些处理,并希望将其存储在更持久的位置,如关系数据库。

本教程介绍了如何从 CSV 文件加载 pandas DataFrame,从完整数据集中提取一些数据,然后使用 SQLAlchemy 将数据子集保存到 SQLite 数据库。

配置我们的开发环境

确保安装了 Python 3。截至目前,Python 3.8.2 是最新的 Python 版本。

在本教程中,我们还将使用:

  • pandas(项目主页和源代码),本教程的版本 1.0.3
  • SQLAlchemy(项目主页和源代码),本教程的版本 1.3.15
  • SQLite (项目主页和源代码),其中 Python 包含一个连接器作为 Python 标准库的一部分

使用以下命令将上述代码库安装到新的 Python 虚拟环境中:

python -m venv pandasexport
source pandasexport/bin/activate

pip install pandas==1.0.3 sqlalchemy==1.3.15

我们的开发环境现在已准备好下载示例 COVID-19 数据集,将其加载到 pandasDataFrame 中,对其执行一些分析,然后保存到 SQLite 数据库中。

获取 COVID-19 数据

在您的网络浏览器中转到下载今天关于 COVID-19 病例全球地理分布的数据页面。它应该类似于以下屏幕截图。

下载 2020 年 3 月 29 日 COVID-19 数据的 CSV 版本。

应该有下载 CSV 格式数据的链接,但该组织在过去几周内多次更改页面布局,这使得很难找到 Excel (XLSX) 以外的格式。如果您在获取 CSV 版本时遇到问题,只需从 GitHub 下载这个版本,它与 2020 年 3 月 28 日下载的副本挂钩。

将 CSV 文件导入 pandas

原始数据在 CSV 文件中,我们需要通过 apandas DataFrame 将其加载到内存中。

首先在命令行上运行 Python Read-Evaluate-Print Loop (REPL):

python

>>>

REPL 已准备好执行代码,但我们首先需要导入 pandas 库以便使用它。

from pandas import read_csv

df = read_csv("covid-19-cases-march-28-2020.csv", encoding="ISO-8859-1")

数据现在被加载到 df 变量中,它是 pandas DataFrame 类的一个实例。

当我们在此 DataFrame 上运行 count 函数时,我们返回它有 7320 行。

df.count()

接下来,我们将获取这组 7320 行数据,并仅切出与美国有关的行。

从原来的DataFrame创建一个新的DataFrame

我们可以使用 pandas 函数将 countriesAndTerritories 列匹配到我们选择的国家/地区,从而挑选出单个国家/地区的所有数据行。

save_df = df[df['countriesAndTerritories']=="United_States_of_America"]

save_df 变量包含较小的数据子集。你可以让它自己打印出来,看看里面有什么:

save_df

您应该看到类似于以下输出的内容:

         dateRep  day  month  year  cases  deaths   countriesAndTerritories geoId countryterritoryCode  popData2018
7082  28/03/2020   28      3  2020  18695     411  United_States_of_America    US                  USA  327167434.0
7083  27/03/2020   27      3  2020  16797     246  United_States_of_America    US                  USA  327167434.0
7084  26/03/2020   26      3  2020  13963     249  United_States_of_America    US                  USA  327167434.0
7085  25/03/2020   25      3  2020   8789     211  United_States_of_America    US                  USA  327167434.0
7086  24/03/2020   24      3  2020  11236     119  United_States_of_America    US                  USA  327167434.0
...          ...  ...    ...   ...    ...     ...                       ...   ...                  ...          ...
7166  04/01/2020    4      1  2020      0       0  United_States_of_America    US                  USA  327167434.0
7167  03/01/2020    3      1  2020      0       0  United_States_of_America    US                  USA  327167434.0
7168  02/01/2020    2      1  2020      0       0  United_States_of_America    US                  USA  327167434.0
7169  01/01/2020    1      1  2020      0       0  United_States_of_America    US                  USA  327167434.0
7170  31/12/2019   31     12  2019      0       0  United_States_of_America    US                  USA  327167434.0

[89 rows x 10 columns]

原始 7320 行中的 89 行数据。让我们继续将这个子集保存到 SQLite 关系数据库。

将 DataFrame 保存到 SQLite

我们将使用 SQLAlchemy 创建一个到新 SQLite 数据库的连接,在本例中,该数据库将存储在名为 save_pandas.db 的文件中。您当然可以使用任何您想要的名称将文件保存在任何位置,而不仅仅是您执行 Python REPL 的目录。

首先从 create_engine 库中导入 sqlalchemy 函数。

from sqlalchemy import create_engine

使用导入的create_engine 函数创建连接,然后在其上调用connect 方法。

engine = create_engine('sqlite:///save_pandas.db', echo=True)
sqlite_connection = engine.connect()

我们设置echo=True 来查看来自我们数据库连接的所有输出。连接成功后,您将看到类似于以下内容的输出:

2020-03-29 20:44:08,198 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2020-03-29 20:44:08,198 INFO sqlalchemy.engine.base.Engine ()
2020-03-29 20:44:08,199 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2020-03-29 20:44:08,199 INFO sqlalchemy.engine.base.Engine ()
<sqlalchemy.engine.base.Connection object at 0x7fd4d932ec88>

用您想要创建的表名的字符串设置一个变量名。然后在 to_sql 对象上调用 save_df 方法时使用该变量,这是我们的 pandas DataFrame,它是原始数据集的一个子集,其中有 89 行是从原来的 7320。

请注意,在这种情况下,如果表已存在于数据库中,我们将失败。您可以将 if_exists 更改为 replaceappend 并在此程序的更强大版本中添加您自己的异常处理。查看 pandas.DataFrame.to_sql 文档以了解有关您的选项的详细信息。

sqlite_table = "Covid19"
save_df.to_sql(sqlite_table, sqlite_connection, if_exists='fail')

echo 输出应该有一堆输出。

2020-03-29 20:45:09,066 INFO sqlalchemy.engine.base.Engine PRAGMA main.table_info("Covid19")
2020-03-29 20:45:09,066 INFO sqlalchemy.engine.base.Engine ()
2020-03-29 20:45:09,067 INFO sqlalchemy.engine.base.Engine PRAGMA temp.table_info("Covid19")
2020-03-29 20:45:09,067 INFO sqlalchemy.engine.base.Engine ()
2020-03-29 20:45:09,069 INFO sqlalchemy.engine.base.Engine 
CREATE TABLE "Covid19" (
    "index" BIGINT, 
    "dateRep" TEXT, 
    day BIGINT, 
    month BIGINT, 
    year BIGINT, 
    cases BIGINT, 
    deaths BIGINT, 
    "countriesAndTerritories" TEXT, 
    "geoId" TEXT, 
    "countryterritoryCode" TEXT, 
    "popData2018" FLOAT
)


2020-03-29 20:45:09,069 INFO sqlalchemy.engine.base.Engine ()
2020-03-29 20:45:09,070 INFO sqlalchemy.engine.base.Engine COMMIT
2020-03-29 20:45:09,070 INFO sqlalchemy.engine.base.Engine CREATE INDEX "ix_Covid19_index" ON "Covid19" ("index")
2020-03-29 20:45:09,070 INFO sqlalchemy.engine.base.Engine ()
2020-03-29 20:45:09,071 INFO sqlalchemy.engine.base.Engine COMMIT
2020-03-29 20:45:09,072 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2020-03-29 20:45:09,074 INFO sqlalchemy.engine.base.Engine INSERT INTO "Covid19" ("index", "dateRep", day, month, year, cases, deaths, "countriesAndTerritories", "geoId", "countryterritoryCode", "popData2018") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2020-03-29 20:45:09,074 INFO sqlalchemy.engine.base.Engine ((7082, '28/03/2020', 28, 3, 2020, 18695, 411, 'United_States_of_America', 'US', 'USA', 327167434.0), (7083, '27/03/2020', 27, 3, 2020, 16797, 246, 'United_States_of_America', 'US', 'USA', 327167434.0), (7084, '26/03/2020', 26, 3, 2020, 13963, 249, 'United_States_of_America', 'US', 'USA', 327167434.0), (7085, '25/03/2020', 25, 3, 2020, 8789, 211, 'United_States_of_America', 'US', 'USA', 327167434.0), (7086, '24/03/2020', 24, 3, 2020, 11236, 119, 'United_States_of_America', 'US', 'USA', 327167434.0), (7087, '23/03/2020', 23, 3, 2020, 8459, 131, 'United_States_of_America', 'US', 'USA', 327167434.0), (7088, '22/03/2020', 22, 3, 2020, 7123, 80, 'United_States_of_America', 'US', 'USA', 327167434.0), (7089, '21/03/2020', 21, 3, 2020, 5374, 110, 'United_States_of_America', 'US', 'USA', 327167434.0)  ... displaying 10 of 89 total bound parameter sets ...  (7169, '01/01/2020', 1, 1, 2020, 0, 0, 'United_States_of_America', 'US', 'USA', 327167434.0), (7170, '31/12/2019', 31, 12, 2019, 0, 0, 'United_States_of_America', 'US', 'USA', 327167434.0))
2020-03-29 20:45:09,074 INFO sqlalchemy.engine.base.Engine COMMIT
2020-03-29 20:45:09,075 INFO sqlalchemy.engine.base.Engine SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
2020-03-29 20:45:09,075 INFO sqlalchemy.engine.base.Engine ()

我们的表格及其所有数据现在应该都设置好了。关闭数据库连接。

sqlite_connection.close()

我们可以通过sqlite3 命令行查看器查看数据,以确保它已正确保存到 SQLite 文件中。

在命令行(不在 Python REPL 中),键入:

sqlite3

这将打开命令行提示符以与 SQLite 数据库进行交互。但是,我们还没有连接到我们的 save_pandas.db 文件。

SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> 

使用 .open 命令和我们的 save_pandas.db 文件名来访问数据库。然后使用标准 SQL 查询从 Covid19 表中获取所有记录。

sqlite> .open save_pandas.db
sqlite> select * from Covid19;

SQLite 资源管理器应该产生如下所示的输出:

7082|28/03/2020|28|3|2020|18695|411|United_States_of_America|US|USA|327167434.0
7083|27/03/2020|27|3|2020|16797|246|United_States_of_America|US|USA|327167434.0
7084|26/03/2020|26|3|2020|13963|249|United_States_of_America|US|USA|327167434.0
7085|25/03/2020|25|3|2020|8789|211|United_States_of_America|US|USA|327167434.0
7086|24/03/2020|24|3|2020|11236|119|United_States_of_America|US|USA|327167434.0
7087|23/03/2020|23|3|2020|8459|131|United_States_of_America|US|USA|327167434.0
7088|22/03/2020|22|3|2020|7123|80|United_States_of_America|US|USA|327167434.0
7089|21/03/2020|21|3|2020|5374|110|United_States_of_America|US|USA|327167434.0
7090|20/03/2020|20|3|2020|4835|0|United_States_of_America|US|USA|327167434.0
7091|19/03/2020|19|3|2020|2988|42|United_States_of_America|US|USA|327167434.0
7092|18/03/2020|18|3|2020|1766|23|United_States_of_America|US|USA|327167434.0
7093|17/03/2020|17|3|2020|887|16|United_States_of_America|US|USA|327167434.0
7094|16/03/2020|16|3|2020|823|12|United_States_of_America|US|USA|327167434.0
7095|15/03/2020|15|3|2020|777|10|United_States_of_America|US|USA|327167434.0
7096|14/03/2020|14|3|2020|511|7|United_States_of_America|US|USA|327167434.0
7097|13/03/2020|13|3|2020|351|10|United_States_of_America|US|USA|327167434.0
7098|12/03/2020|12|3|2020|287|2|United_States_of_America|US|USA|327167434.0
7099|11/03/2020|11|3|2020|271|2|United_States_of_America|US|USA|327167434.0
7100|10/03/2020|10|3|2020|200|5|United_States_of_America|US|USA|327167434.0
7101|09/03/2020|9|3|2020|121|4|United_States_of_America|US|USA|327167434.0
7102|08/03/2020|8|3|2020|95|3|United_States_of_America|US|USA|327167434.0
7103|07/03/2020|7|3|2020|105|2|United_States_of_America|US|USA|327167434.0
7104|06/03/2020|6|3|2020|74|1|United_States_of_America|US|USA|327167434.0
7105|05/03/2020|5|3|2020|34|2|United_States_of_America|US|USA|327167434.0
7106|04/03/2020|4|3|2020|22|3|United_States_of_America|US|USA|327167434.0
7107|03/03/2020|3|3|2020|14|4|United_States_of_America|US|USA|327167434.0
7108|02/03/2020|2|3|2020|20|1|United_States_of_America|US|USA|327167434.0
7109|01/03/2020|1|3|2020|3|1|United_States_of_America|US|USA|327167434.0
7110|29/02/2020|29|2|2020|6|0|United_States_of_America|US|USA|327167434.0
7111|28/02/2020|28|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7112|27/02/2020|27|2|2020|6|0|United_States_of_America|US|USA|327167434.0
7113|26/02/2020|26|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7114|25/02/2020|25|2|2020|18|0|United_States_of_America|US|USA|327167434.0
7115|24/02/2020|24|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7116|23/02/2020|23|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7117|22/02/2020|22|2|2020|19|0|United_States_of_America|US|USA|327167434.0
7118|21/02/2020|21|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7119|20/02/2020|20|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7120|19/02/2020|19|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7121|18/02/2020|18|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7122|17/02/2020|17|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7123|16/02/2020|16|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7124|15/02/2020|15|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7125|14/02/2020|14|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7126|13/02/2020|13|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7127|12/02/2020|12|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7128|11/02/2020|11|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7129|10/02/2020|10|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7130|09/02/2020|9|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7131|08/02/2020|8|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7132|07/02/2020|7|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7133|06/02/2020|6|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7134|05/02/2020|5|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7135|04/02/2020|4|2|2020|0|0|United_States_of_America|US|USA|327167434.0
7136|03/02/2020|3|2|2020|3|0|United_States_of_America|US|USA|327167434.0
7137|02/02/2020|2|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7138|01/02/2020|1|2|2020|1|0|United_States_of_America|US|USA|327167434.0
7139|31/01/2020|31|1|2020|1|0|United_States_of_America|US|USA|327167434.0
7140|30/01/2020|30|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7141|29/01/2020|29|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7142|28/01/2020|28|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7143|27/01/2020|27|1|2020|3|0|United_States_of_America|US|USA|327167434.0
7144|26/01/2020|26|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7145|25/01/2020|25|1|2020|1|0|United_States_of_America|US|USA|327167434.0
7146|24/01/2020|24|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7147|23/01/2020|23|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7148|22/01/2020|22|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7149|21/01/2020|21|1|2020|1|0|United_States_of_America|US|USA|327167434.0
7150|20/01/2020|20|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7151|19/01/2020|19|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7152|18/01/2020|18|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7153|17/01/2020|17|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7154|16/01/2020|16|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7155|15/01/2020|15|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7156|14/01/2020|14|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7157|13/01/2020|13|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7158|12/01/2020|12|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7159|11/01/2020|11|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7160|10/01/2020|10|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7161|09/01/2020|9|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7162|08/01/2020|8|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7163|07/01/2020|7|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7164|06/01/2020|6|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7165|05/01/2020|5|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7166|04/01/2020|4|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7167|03/01/2020|3|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7168|02/01/2020|2|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7169|01/01/2020|1|1|2020|0|0|United_States_of_America|US|USA|327167434.0
7170|31/12/2019|31|12|2019|0|0|United_States_of_America|US|USA|327167434.0
sqlite> 

countriesAndTerritories 列匹配United_States_of_America 的所有数据都在那里!我们成功地将数据从 DataFrame 导出到 SQLite 数据库文件中。

下一步是什么?

我们只是将数据从 CSV 导入到 pandas DataFrame,选择该数据的一个子集,然后将其保存到关系数据库。

您应该查看通过探索 COVID-19 数据来学习 pandas 教程,以了解有关如何从更大的 DataFrame 中选择数据子集的更多信息,或者前往 pandas 页面以获取 Python 社区其他成员提供的更多教程。

您还可以通过阅读 Full Stack Python 目录页面了解在您的 Python 项目中接下来要编写什么代码。

有问题吗?通过 Twitter@fullstackpython 或@mattmakai 与我联系。我也在 GitHub 上,用户名是 mattmakai。

这篇文章有问题吗?在 GitHub 上创建此页面的源代码并提交拉取请求。

未经允许不得转载:我爱分享网 » 使用 SQLAlchemy 将 pandas DataFrame 导出到 SQLite

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏