使用Pandas的Pandasql中的SQL
使用Pandasql库中的SQL语句进行数据处理
如果你只能为数据科学工具箱添加一项技能,并且毋庸置疑地说,最重要的是SQL。然而,在Python数据分析生态系统中,pandas 是一个强大且流行的库。
但是,如果你对pandas还不熟悉,学习pandas的函数——如分组、聚合、连接等——可能会让人觉得难以应付。相比之下,用SQL查询数据框会更容易。这就是pandasql库的用途所在!
那么,让我们学习如何使用pandasql库在一个示例数据集上运行SQL查询。
Pandasql初步
在继续学习之前,让我们先准备好我们的工作环境。
安装pandasql
如果你使用的是Google Colab,你可以使用 `pip` 安装pandasql并跟随以下代码:
pip install pandasql
如果你在本地机器上使用Python,请确保你为该项目安装了专用的虚拟环境,并且已经安装了pandas和Seaborn库。你可以使用内置的venv包来创建和管理虚拟环境。
我在Ubuntu LTS 22.04上运行Python 3.11。所以下面的说明适用于Ubuntu(在Mac上也可以工作)。如果你使用的是Windows机器,请参考这些说明来创建和激活虚拟环境。
要在你的项目目录中创建一个虚拟环境(这里命名为v1),请运行以下命令:
python3 -m venv v1
然后激活虚拟环境:
source v1/bin/activate
现在安装pandas、seaborn和pandasql:
pip3 install pandas seaborn pandasql
注意:如果你还没有安装`pip`,你可以通过运行命令`apt install python3-pip`来更新系统包并安装它。
`sqldf`函数
要在pandas数据框上运行SQL查询,你可以使用以下语法导入和使用sqldf:
from pandasql import sqldfsqldf(query, globals())
这里,
query表示你想在pandas数据框上执行的SQL查询。它应该是一个包含有效SQL查询的字符串。globals()指定了查询中使用的数据框所在的全局命名空间。
使用Pandasql查询Pandas数据框
让我们从导入所需的包和从pandasql导入sqldf函数开始:
import pandas as pdimport seaborn as snsfrom pandasql import sqldf
由于我们将在数据框上运行多个查询,我们可以定义一个函数,以便我们可以通过将查询作为参数传递给函数来调用它:
# 定义一个可重用的用于运行SQL查询的函数run_query = lambda query: sqldf(query, globals())
对于接下来的所有示例,我们将运行run_query函数(该函数在底层使用sqldf())在tips_df数据框上执行SQL查询。然后,我们将打印出返回的结果。
加载数据集
在这个教程中,我们将使用内置于 Seaborn 库中的 “tips” 数据集。”tips” 数据集包含有关餐厅小费的信息,包括总账单、小费金额、支付者的性别、星期几等等。
将“tips”数据集加载到数据框 tips_df 中:
# 将“tips”数据集加载到 pandas 数据框中tips_df = sns.load_dataset("tips")
示例 1 – 选择数据
这是我们的第一个查询 – 一个简单的 SELECT 语句:
# 简单的选择查询语句query_1 = """SELECT *FROM tips_dfLIMIT 10;"""result_1 = run_query(query_1)print(result_1)
如上所示,此查询从 tips_df 数据框中选择所有列,并使用 `LIMIT` 关键字将输出限制为前 10 行。它等价于在 pandas 中执行 tips_df.head(10):

示例 2 – 基于条件进行筛选
接下来,让我们编写一个根据条件筛选结果的查询:
# 基于条件进行筛选的查询query_2 = """SELECT *FROM tips_dfWHERE total_bill > 30 AND tip > 5;"""result_2 = run_query(query_2)print(result_2)
此查询根据 WHERE 子句中指定的条件筛选 tips_df 数据框。它选择 `tips_df` 数据框中“总账单”大于 30 且“小费”金额大于 5 的所有列。
运行 query_2 会得到以下结果:

示例 3 – 分组和聚合
让我们运行以下查询,按天来获取平均账单金额:
# 分组和聚合查询query_3 = """SELECT day, AVG(total_bill) as avg_billFROM tips_dfGROUP BY day;"""result_3 = run_query(query_3)print(result_3)
以下是输出结果:
我们可以看到周末的平均账单金额稍高。
让我们再看一个关于分组和聚合的例子。考虑以下查询:
query_4 = """SELECT day, COUNT(*) as num_transactions, AVG(total_bill) as avg_bill, MAX(tip) as max_tipFROM tips_dfGROUP BY day;"""result_4 = run_query(query_4)print(result_4)
查询 query_4 将 `tips_df` 数据框中的数据按 ‘day’ 列进行分组,并计算每个分组的以下聚合函数:
num_transactions:交易数量的计数,avg_bill:’total_bill’ 列的平均值,max_tip:’tip’ 列的最大值。
如上所示,我们按天分组得到了以上结果:

示例 4 – 子查询
让我们添加一个使用子查询的示例查询:
# 子查询query_5 = """SELECT *FROM tips_dfWHERE total_bill > (SELECT AVG(total_bill) FROM tips_df);"""result_5 = run_query(query_5)print(result_5)
在这里,
- 内部子查询计算
tips_df数据帧的‘total_bill’列的平均值。 - 外部查询然后选择
tips_df数据帧中‘total_bill’大于计算出的平均值的所有列。
运行query_5将得到以下结果:

示例5 – 合并两个数据帧
我们只有一个数据帧。要执行简单的合并操作,让我们创建另一个数据帧如下:
# 创建另一个要与tips_df进行合并的数据帧other_data = pd.DataFrame({ 'day': ['Thur','Fri', 'Sat', 'Sun'], 'special_event': ['Throwback Thursday', 'Feel Good Friday', 'Social Saturday','Fun Sunday', ]})
other_data数据帧将每天与一个特殊事件相关联。
现在让我们在共同的‘day’列上执行一个LEFT JOIN操作,将tips_df和other_data数据帧合并:
query_6 = """SELECT t.*, o.special_eventFROM tips_df tLEFT JOIN other_data o ON t.day = o.day;"""result_6 = run_query(query_6)print(result_6)
这是合并操作的结果:

总结和下一步
在本教程中,我们介绍了如何使用pandasql在pandas数据帧上运行SQL查询。尽管pandasql使使用SQL查询数据帧变得非常简单,但也存在一些限制。
关键的限制是pandasql可能比本地的pandas慢几个数量级。那么你应该怎么办呢?嗯,如果你需要使用pandas进行数据分析,当你正在学习pandas并且迅速上手时,你可以使用pandasql查询数据帧。然后,一旦你熟悉了pandas,你可以切换到pandas或类似Polars的其他库。
为了朝着这个方向迈出第一步,试着编写并运行到目前为止我们已经运行过的SQL查询的pandas等效代码。本教程中使用的所有代码示例都在GitHub上。继续编程! Bala Priya C是一位来自印度的开发人员和技术作家。她喜欢在数学、编程、数据科学和内容创作的交汇处工作。她感兴趣和擅长的领域包括DevOps、数据科学和自然语言处理。她喜欢阅读、写作、编码和咖啡!目前,她正在通过编写教程、指南、评论文章等来学习和与开发者社区分享知识。





