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的例子
现在,我们将更详细地看看如何使用pandasql
的sqldf
函数在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