Pandas是近年來最好的數據操作庫之一。它允許切片、分組、連接和執行任意數據轉換。如果你熟練的使用SQL,那麼這篇文章將介紹一種更直接、簡單的使用Pandas處理大多數數據操作案例。
假設你對SQL非常的熟悉,或者你想有更可讀的代碼。或者您只是想在dataframe上運行一個特殊的SQL查詢。或者,也許你來自R,想要一個sqldf的替代品。
這篇文章將介紹一種在pandas的dataframe中使用SQL的python包,並且使用一個不等連結的查詢操作來介紹PandasSQL的使用方法。
不等連接(Non-equi join)
假設你必須連接兩個dataframe。其中一個顯示了我們對某些商品進行促銷的時間段。第二個是事務Dataframe。我想知道促銷活動推動的銷售情況,也就是促銷期間的銷售情況。
我們可以通過聯接項目列以及聯接條件(TransactionDt≥StartDt和TransactionDt≤EndDt)來實現這一點。因為現在我們的連接條件也有大於號和小於號,這樣的連接稱為不等連接。在繼續之前,一定要考慮如何在pandas中做這樣的事情。
pandas的解決方案
那麼在pandas身上該怎麼做呢?pandas肯定可以解決這個問題,儘管我認為它的可讀性不夠。
讓我們從生成一些要處理的隨機數據開始。
import pandas as pd import random import datetime def random_dt_bw(start_date,end_date): days_between = (end_date - start_date).days random_num_days = random.randrange(days_between) random_dt = start_date + datetime.timedelta(days=random_num_days) return random_dt def generate_data(n=1000): items = [f"i_{x}" for x in range(n)] start_dates = [random_dt_bw(datetime.date(2020,1,1),datetime.date(2020,9,1)) for x in range(n)] end_dates = [x + datetime.timedelta(days=random.randint(1,10)) for x in start_dates] offerDf = pd.DataFrame({"Item":items, "StartDt":start_dates, "EndDt":end_dates}) transaction_items = [f"i_{random.randint(0,n)}" for x in range(5*n)] transaction_dt = [random_dt_bw(datetime.date(2020,1,1),datetime.date(2020,9,1)) for x in range(5*n)] sales_amt = [random.randint(0,1000) for x in range(5*n)] transactionDf = pd.DataFrame({"Item":transaction_items,"TransactionDt":transaction_dt,"Sales":sales_amt}) return offerDf,transactionDf
您不需要擔心上面的隨機數據生成代碼。只要知道我們的隨機數據是什麼樣子就可以了:
offerDf,transactionDf = generate_data(n=100000)
一旦我們有了數據,我們就可以通過合併列項上的數據來進行不等連接,然後根據所需條件進行過濾。
merged_df = pd.merge(offerDf,transactionDf,on='Item')pandas_solution = merged_df[(merged_df['TransactionDt']>=merged_df['StartDt']) & (merged_df['TransactionDt']<=merged_df['EndDt'])]
結果如下,正如我們所希望的:
PandaSQL解決方案
Pandas解決方案很好,可以做我們想做的事情,但是我們也可以使用PandaSQL以一種可讀性更強的方式完成同樣的事情。
PandaSQL是什麼?
PandaSQL為我們提供了在panda數據資料庫上編寫SQL的方法。因此,如果您已經編寫了一些SQL查詢,那麼使用pandaSQL可能比將它們轉換為panda語法更有意義。為了開始使用PandaSQL,我們簡單地安裝它:
pip install -U pandasql
安裝了pandaSQL之後,我們可以通過創建pysqldf函數來使用它,該函數接受一個查詢作為輸入,並運行該查詢來返回一個Pandas DF。不用擔心語法,因為跟使用pandas差不多。
from pandasql import sqldfpysqldf = lambda q: sqldf(q, globals())
現在,我們可以使用這個函數在我們的pandas dataframe上運行任何SQL查詢。下面是不等連接,我們希望使用可讀性更強的SQL格式。
q = """SELECT A.*,B.TransactionDt,B.Sales FROM offerDf A INNER JOIN transactionDf B ON A.Item = B.Item AND A.StartDt <= B.TransactionDt AND A.EndDt >= B.TransactionDt; """pandaSQL_solution = pysqldf(q)
結果是一個我們所期望的panda Dataframe。索引已經自動為我們重置了,不像以前那樣需要手動操作。
警告
雖然PandaSQL函數允許我們在我們的panda數據框架上運行SQL查詢,並且在某些情況下是一個非常好的工具,但是它的性能不如純panda語法。
當我們用可讀性更強的PandaSQL為pandas計時時,我們發現PandaSQL花費的時間大約是原生pandas的10倍。
結論
雖然PandaSQL庫的性能不如本地的panda,但當我們想進行特別分析時,它是對我們的數據分析工具箱的一個很好的補充,而且對於那些更習慣使用SQL查詢的人來說。
想要更深入地了解這篇文章的代碼,請訪問我的GitHub知識庫,在那裡你可以找到這篇文章和我所有的文章的代碼。
github/MLWhiz/datascienceblogs/tree/master/pandasql
譯者註:我一直在尋找能夠使用sql處理pandas的dataframe的解決方案,pandasSQL在這這方面起到了很好的開端,雖然他的性能還不足以在生產環境中使用,但是我們再進行EDA和數據分析等一次性的操作的時候完全可以使用sql替代複雜的pandas的查詢語法。所以如果你跟我一樣,對SQL非常熟悉,並且厭倦了pandas的複雜語法,pandasSQL是一個很好的解決方案
作者:Rahul Agarwal
deephub翻譯組