譯者 | 布加迪
審校 | 重樓
SQL(即結(jié)構(gòu)化查詢語言)長期以來一直是數(shù)據(jù)管理的首選工具,但有時(shí)它不盡如人意,需要Python等工具的強(qiáng)大功能和靈活性。Python是一種通用的多用途編程語言,擅長訪問、提取、處理和探索關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)。Python中的開源庫Pandas專門用于數(shù)據(jù)操縱和分析。
我們在本教程中將探討何時(shí)以及如何將SQL功能整合到Pandas框架中,并探討其局限性。
現(xiàn)在你可能想知道的主要問題是……
為什么兩者都使用?
原因在于可讀性和熟悉度:在某些情況下,尤其是在復(fù)雜的工作流中,SQL查詢可以比等效的Pandas代碼更清晰、更容易閱讀。對于那些在改用Pandas之前開始用SQL處理數(shù)據(jù)的人來說,尤其如此。
此外,由于大多數(shù)數(shù)據(jù)源自數(shù)據(jù)庫,SQL作為這些數(shù)據(jù)庫的原生語言,提供了天然的優(yōu)勢。這就是為什么許多數(shù)據(jù)專業(yè)人員(特別是數(shù)據(jù)科學(xué)家)經(jīng)常在同一數(shù)據(jù)管道中整合SQL和Python(具體是Pandas),以發(fā)揮兩者之所長。
要查看實(shí)際的SQL可讀性,不妨使用下面的pokemon gen1 pokedex csv文件。
設(shè)想我們希望按“Total”列按升序?qū)?/span>DataFrame進(jìn)行排序,并顯示前5個(gè)?,F(xiàn)在我們可以比較如何使用Pandas和SQL執(zhí)行相同的操作。
結(jié)合使用Python和Pandas:
data[["#", "Name", "Total"]].sort_values(by="Total", ascending=True).head(5)
使用SQL:
SELECT
"#",
Name,
Total
FROM data
ORDER BY Total
LIMIT 5
你看到兩者有多不同了吧?但是…我們?nèi)绾?/span>在我們的工作環(huán)境中將這兩種語言與Python結(jié)合起來?
解決辦法就是使用PandaSQL!
使用PandaSQL
Pandas是一個(gè)功能強(qiáng)大的開源數(shù)據(jù)分析和操縱python庫。PandaSQL允許用戶使用SQL語法來查詢Pandas DataFrame。對于剛接觸Pandas的人來說,PandaSQL試圖使數(shù)據(jù)操縱和清理讓人更熟悉。你可以使用PandaSQL利用SQL語法查詢Pandas DataFrame。
不妨看一看。
首先,我們需要安裝PandaSQL:
pip install pandasql
然后與往常一樣,我們導(dǎo)入所需的軟件包:
from pandasql import sqldf
在這里,我們直接從PandaSQL導(dǎo)入sqldf函數(shù),這實(shí)際上是該庫的核心特性。顧名思義,sqldf允許你使用SQL語法查詢DataFrame。
sqldf (query_string env =None)
在此上下文中,query_string是必需的參數(shù),它接受字符串格式的SQL查詢。env參數(shù)是可選的,很少使用,可以設(shè)置為locals()或globals(),使sqldf能夠訪問Python環(huán)境中指定范圍內(nèi)的變量。
除了這個(gè)函數(shù)外,PandaSQL還包括兩個(gè)基本的內(nèi)置數(shù)據(jù)集,它們可以用簡單的函數(shù)load_births()和load_meat()來加載。這樣,你就可以使用內(nèi)置的一些虛擬數(shù)據(jù)。
現(xiàn)在,如果我們想在Python Jupyter筆記本中執(zhí)行前面的SQL查詢,它將像下面這樣:
from pandasql import sqldf
import pandas as pd
sqldf('''
SELECT "#", Name, Total
FROM data
ORDER BY Total
LIMIT 5''')
sqldf函數(shù)將查詢結(jié)果作為Pandas DataFrame返回。
我們應(yīng)該什么時(shí)候使用它?
pandasql庫支持使用SQL的數(shù)據(jù)查詢語言(DQL)進(jìn)行數(shù)據(jù)操縱,提供了一種熟悉的、基于SQL的方法與Pandas DataFrame中的數(shù)據(jù)進(jìn)行交互。
借助pandasql,你可以直接對數(shù)據(jù)集執(zhí)行查詢,從而實(shí)現(xiàn)高效的數(shù)據(jù)檢索、過濾、排序、分組、連接和聚合。
此外,它支持執(zhí)行數(shù)學(xué)和邏輯操作,使其成為精通SQL的用戶使用Python處理數(shù)據(jù)的一種強(qiáng)大工具。
PandaSQL僅限于SQL的數(shù)據(jù)查詢語言(DQL)子集,這意味著它不支持修改表,也不支持UPDATE、INSERT或DELETE等數(shù)據(jù)操作。
此外,由于PandaSQL依賴SQL語法,具體是SQLite,因此必須注意可能影響查詢行為的SQLite特有的怪癖。
比較PandasSQL和SQL
本節(jié)演示如何使用PandaSQL和Pandas來實(shí)現(xiàn)相似的結(jié)果,并提供橫向比較以突出它們各自的方法。
- 生成多個(gè)表
不妨從更龐大的數(shù)據(jù)集生成數(shù)據(jù)子集,創(chuàng)建類型、特性等表。使用PandaSQL,我們可以指定SQL查詢來選擇特定的列,從而易于提取我們想要的確切數(shù)據(jù)。
使用PandaSQL:
types = sqldf('''
SELECT "#", Name, "Type 1", "Type 2"
FROM data''')
legendaries = sqldf('''
SELECT "#", Name, Legendary
FROM data''')
generations = sqldf('''
SELECT "#", Name, Generation
FROM data''')
features = sqldf('''
SELECT "#", Name, Total, HP, Attack, Defense, "Sp. Atk", "Sp. Def","Speed"
FROM data''')
這里,PandaSQL支持一種干凈的、基于SQL的選擇語法,對于熟悉關(guān)系數(shù)據(jù)庫的用戶來說,這種語法非常直觀。如果數(shù)據(jù)選擇涉及復(fù)雜的條件或SQL函數(shù),它特別有用。
使用純Python:
# Selecting columns for types
types = data[['#', 'Name', 'Type 1', 'Type 2']]
# Selecting columns for legendaries
legendaries = data[['#','Name', 'Legendary']]
# Selecting columns for generations
generations = data[['#','Name', 'Generation']]
# Selecting columns for features
features = data[['#','Name', 'Total', 'HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed']]
在純Python中,我們只需在方括號內(nèi)指定列名即可獲得相同的結(jié)果。雖然這對于直接的列選擇很高效,但是對于較復(fù)雜的過濾或分組條件,可讀性可能會降低,在這種條件下,SQL風(fēng)格的語法可能更自然。
- 執(zhí)行連接
連接是基于公共列組合來自多個(gè)數(shù)據(jù)源的數(shù)據(jù)的強(qiáng)大方法,PandaSQL和Pandas都支持此功能。
首先,PandaSQL:
types_features = sqldf('''
SELECT
t1.*,
t2.Total,
t2.HP,
t2.Attack,
t2.Defense,
t2."Sp. Atk",
t2."Sp. Def",
t2."Speed"
FROM types AS t1
LEFT JOIN features AS t2
ON t1."#" = t2."#"
AND t1.Name = t2.Name
’’’)
使用SQL,這個(gè)LEFT JOIN基于#和Name列中的匹配值組合類型和特性。這種方法對于SQL用戶來說很簡單,用于從多個(gè)表選擇特定列和組合數(shù)據(jù)的語法很清晰。
在純Python中:
# Performing a left join between `types` and `features` on the columns "#" and "Name"
types_features = types.merge(
features,
on=['#', 'Name'],
how='left'
)
types_features
在純Python中,我們使用merge()函數(shù)完成相同的結(jié)果,指定匹配列以及how='left'來執(zhí)行左連接。Pandas使合并多列變得很容易,并在指定連接類型方面提供了靈活性。然而,在處理較大的表或執(zhí)行較復(fù)雜的連接時(shí),SQL類型的連接語法更具可讀性。
- 自定義查詢
在該示例中,我們基于“Defense”按降序檢索前5條記錄。
PandaSQL:
top_5_defense = sqldf('''
SELECT
Name, Defense
FROM features
ORDER BY Defense DESC
LIMIT 5
''')
SQL查詢按Defense列按降序?qū)μ匦赃M(jìn)行排序,并將結(jié)果限制為前5個(gè)條目。這種方法很直接,特別是對于SQL用戶,ORDER BY和LIMIT關(guān)鍵字明確了查詢的作用。
在純Python中:
top_5_defense = features[['Name', 'Defense']].sort_values(by='Defense', ascending=False).head(5)
僅使用Python,我們使用sort_values()按Defense排序,然后使用head(5)來限制輸出,從而獲得相同的結(jié)果。Pandas為排序和選擇記錄提供了一種靈活而直觀的語法,不過經(jīng)常處理數(shù)據(jù)庫的人可能更熟悉SQL方法。
結(jié)論
我們在本教程中研究了如何以及何時(shí)結(jié)合SQL功能與Pandas有助于生成更干凈、更高效的代碼。我們介紹了PandaSQL庫的設(shè)置和使用以及局限性,并演示了幾個(gè)流行的示例,以比較PandaSQL代碼與等效的Pandas Python代碼。
通過比較這些方法,你可以看到,PandaSQL對于熟悉SQL的用戶或具有復(fù)雜查詢的場景很有幫助,而原生Pandas代碼對于習(xí)慣于使用Python的用戶來說可能更符合Python、更有機(jī)整合。
你可以在下面的Jupyter Notebook中查看本文顯示的所有代碼:https://www.kdnuggets.com/using-pandas-and-sql-together-for-data-analysis。
原文標(biāo)題:Using Pandas and SQL Together for Data Analysis,作者:Josep Ferrer