如何在pandas中使用SQL,通过pandasql查询

SQL,或结构化查询语言,是一种用于访问、提取、操作和探索存储在关系数据库中的数据的编程语言。pandas 是一个专门为数据操作和分析设计的 Python 开源库。

在本教程中,我们将讨论何时以及如何(以及何时不能)在 pandas 框架中使用 SQL 功能。此外,我们还将查看各种实现此方法的示例,并将其与纯 pandas 中的等效代码进行比较。

为什么在 pandas 中使用 SQL?

鉴于引言中的定义,为什么有人想要结合使用 SQL 和 pandas,尤其是后者是一个全能的数据分析包?

答案是,在某些情况下,尤其是在复杂的程序中,SQL 查询看起来比 pandas 中的相应代码更直观、更容易阅读。这对于那些最初使用 SQL 处理数据,然后后来学习 pandas 的人来说尤其如此。

如果你需要更多关于 pandas 的培训,可以查看我们的pandas 数据操作课程和pandas 教程:Python 中的 DataFrames

为了看到SQL的可读性在实际操作中的作用,假设我们有一个名为penguins的表(数据框),其中包含有关企鹅的各种信息(稍后在这个教程中我们将使用这样一个表)。为了提取所有独特物种的企鹅,它们是雄性并且有超过210毫米的脚蹼,我们在pandas中需要以下代码:

penguins[(penguins['sex'] == 'Male') & (penguins['flipper_length_mm'] > 210)]['species'].unique()

相反,使用SQL获取相同信息,我们将运行以下代码:

SELECT DISTINCT species FROM penguins WHERE sex = 'Male' AND flipper_length_mm > 210

第二段代码,用SQL编写,几乎像一个自然英语句子,因此要直观得多。我们可以通过将其跨越多行来进一步增加其可读性:

SELECT DISTINCT species FROM penguins WHERE sex = 'Male' AND flipper_length_mm > 210

现在我们已经确定了使用SQL对pandas的优势,让我们看看如何将它们两者技术性地结合起来。

如何使用pandasql

pandasql Python库允许通过运行SQL命令来查询pandas数据框,而无需连接到任何SQL服务器。在幕后,它使用SQLite语法,自动检测任何pandas数据框,并将其视为一个普通的SQL表。

设置你的环境

首先,我们需要安装pandasql:

pip install pandasql

然后,我们导入所需的包:

from pandasql import sqldf import pandas as pd

上述内容中,我们直接从pandasql库导入了sqldf函数,这个函数实际上是该库唯一有意义的函数。顾名思义,它用于使用SQL语法查询数据框。除了这个函数,pandasql还提供了两个简单的内置数据集,可以使用自解释的函数load_births()load_meat()加载。

pandasql语法

sqldf函数的语法非常简单:

sqldf(query, env=None)

这里,query是一个必需的参数,它接受一个SQL查询作为字符串,env是一个可选的(并且很少有用)的参数,可以是locals()globals(),它允许sqldf访问您Python环境中的相应变量集。

sqldf函数返回查询结果作为pandas数据框。

何时可以使用pandasql

pandasql库允许使用数据查询语言(DQL)处理数据,这是SQL的一个子集。换句话说,使用pandasql,我们可以在数据库中运行查询,以获取其中的必要信息。特别是,我们可以访问、提取、筛选、排序、分组、联接、聚合数据,以及对它执行数学或逻辑操作。

何时不能使用pandasql

pandasql除了DQL之外,不允许使用SQL的任何其他子集。这意味着我们无法使用pandasql来修改(更新、截断、插入等)表或更改(更新、删除或插入)表中的数据。

此外,由于这个库是基于SQL语法的,我们应该注意SQLite已知的怪癖

使用pandasql的例子

现在,我们将更详细地看看如何使用pandasqlsqldf函数在pandas数据框上运行SQL查询。为了有一些数据来练习,让我们加载seaborn库的一个内置数据集——penguins

import seaborn as sns penguins = sns.load_dataset('penguins') print(penguins.head())

输出

species island bill_length_mm bill_depth_mm flipper_length_mm \ 0 Adelie Torgersen 39.1 18.7 181.0 1 Adelie Torgersen 39.5 17.4 186.0 2 Adelie Torgersen 40.3 18.0 195.0 3 Adelie Torgersen NaN NaN NaN 4 Adelie Torgersen 36.7 19.3 193.0 body_mass_g sex 0 3750.0 Male 1 3800.0 Female 2 3250.0 Female 3 NaN NaN 4 3450.0 Female

如果你需要刷新你的SQL技能,我们的SQL基础技能轨道是一个很好的参考点。

使用pandasql提取数据

print(sqldf('''SELECT species, island FROM penguins LIMIT 5'''))

输出

species island 0 Adelie Torgersen 1 Adelie Torgersen 2 Adelie Torgersen 3 Adelie Torgersen 4 Adelie Torgersen

在上面的例子中,我们从penguins数据框中提取了前五个企鹅的物种和地理信息。注意运行sqldf函数后返回的是一个pandas数据框:

print(type(sqldf('''SELECT species, island FROM penguins LIMIT 5''')))

输出

<class 'pandas.core.frame.DataFrame'>

在纯pandas中,它会是这样的:

print(penguins[['species', 'island']].head())

输出

species island 0 Adelie Torgersen 1 Adelie Torgersen 2 Adelie Torgersen 3 Adelie Torgersen 4 Adelie Torgersen

另一个例子是从一列中提取唯一值:

print(sqldf('''SELECT DISTINCT species FROM penguins'''))

输出

species 0 Adelie 1 Chinstrap 2 Gentoo

在pandas中,它会是这样的:

print(penguins['species'].unique())

输出

['Adelie' 'Chinstrap' 'Gentoo']

使用pandasql对数据进行排序

print(sqldf('''SELECT body_mass_g FROM penguins ORDER BY body_mass_g DESC LIMIT 5'''))

输出

body_mass_g 0 6300.0 1 6050.0 2 6000.0 3 6000.0 4 5950.0

在上面的例子中,我们按体重大小对企鹅进行降序排序,并显示了体重的最高五个值。

在pandas中,它会是这样:

print(penguins['body_mass_g'].sort_values(ascending=False, ignore_index=True).head())

输出:

0 6300.0 1 6050.0 2 6000.0 3 6000.0 4 5950.0 Name: body_mass_g, dtype: float64

使用pandasql过滤数据

让我们尝试一下在“为什么在pandas中使用SQL”章节提到的同一个例子:提取那些是雄性且翼展长度超过210毫米的企鹅的独特种类:

print(sqldf('''SELECT DISTINCT species FROM penguins WHERE sex = 'Male' AND flipper_length_mm > 210'''))

输出:

species 0 Chinstrap 1 Gentoo

在上面,我们基于两个条件过滤数据:sex = 'Male'flipper_length_mm > 210

在pandas中同样的代码看起来会有些复杂:

print(penguins[(penguins['sex'] == 'Male') & (penguins['flipper_length_mm'] > 210)]['species'].unique())

输出:

['Chinstrap' 'Gentoo']

使用pandasql对数据进行分组和聚合

现在,让我们对数据帧中的每种企鹅找到最长的喙进行数据分组和聚合:

print(sqldf('''SELECT species, MAX(bill_length_mm) FROM penguins GROUP BY species'''))

输出:

species MAX(bill_length_mm) 0 Adelie 46.0 1 Chinstrap 58.0 2 Gentoo 59.6

pandas中同样的代码:

print(penguins[['species', 'bill_length_mm']].groupby('species', as_index=False).max())

输出:

species bill_length_mm 0 Adelie 46.0 1 Chinstrap 58.0 2 Gentoo 59.6

使用pandasql执行数学运算

使用pandasql,我们可以轻松地对数据执行数学或逻辑操作。假设我们想计算每只企鹅的喙长与深度的比例,并显示这项测量的前五个值:

print(sqldf('''SELECT bill_length_mm / bill_depth_mm AS length_to_depth FROM penguins ORDER BY length_to_depth DESC LIMIT 5'''))

输出:

length_to_depth 0 3.612676 1 3.510490 2 3.505882 3 3.492424 4 3.458599

注意这次,我们为比例值列使用了别名length_to_depth。否则,我们会得到一个名字恐怖的列 bill_length_mm / bill_depth_mm

在pandas中,我们首先需要创建一个带有比例值的新列:

penguins['length_to_depth'] = penguins['bill_length_mm'] / penguins['bill_depth_mm'] print(penguins['length_to_depth'].sort_values(ascending=False, ignore_index=True).head())

输出:

0 3.612676 1 3.510490 2 3.505882 3 3.492424 4 3.458599 Name: length_to_depth, dtype: float64

结论

总而言之,在本教程中,我们探讨了为什么以及何时可以将SQL的功能与pandas结合起来,以编写更好、更高效的代码。我们讨论了如何设置和使用pandasql库来实现这一目的,以及该包的局限性。最后,我们考虑了pandasql在实际应用中的许多流行示例,并在每种情况下将代码与其pandas对应代码进行了比较。

现在,您拥有了将SQL应用于pandas在实际项目中的所有必要知识。一个很好的练习场所是DataLab,DataCamp的AI支持数据笔记本,具有出色的SQL支持。

Source:
https://www.datacamp.com/tutorial/how-to-use-sql-in-pandas-using-pandasql-queries