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肯定可以解决这个问题,尽管我认为它的可读性不够。
让我们从生成一些要处理的随机数据开始。
importpandasaspdimportrandomimportdatetimedefrandom_dt_bw(start_date,end_date): days_between= (end_date-start_date).daysrandom_num_days=random.randrange(days_between) random_dt=start_date+datetime.timedelta(days=random_num_days) returnrandom_dtdefgenerate_data(n=1000): items= [f"i_{x}"forxinrange(n)] start_dates= [random_dt_bw(datetime.date(2020,1,1),datetime.date(2020,9,1)) forxinrange(n)] end_dates= [x+datetime.timedelta(days=random.randint(1,10)) forxinstart_dates] offerDf=pd.DataFrame({"Item":items, "StartDt":start_dates, "EndDt":end_dates}) transaction_items= [f"i_{random.randint(0,n)}"forxinrange(5*n)] transaction_dt= [random_dt_bw(datetime.date(2020,1,1),datetime.date(2020,9,1)) forxinrange(5*n)] sales_amt= [random.randint(0,1000) forxinrange(5*n)] transactionDf=pd.DataFrame({"Item":transaction_items,"TransactionDt":transaction_dt,"Sales":sales_amt}) returnofferDf,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,我们简单地安装它:
pipinstall-Upandasql
安装了pandaSQL之后,我们可以通过创建pysqldf函数来使用它,该函数接受一个查询作为输入,并运行该查询来返回一个Pandas DF。不用担心语法,因为跟使用pandas差不多。
frompandasqlimportsqldfpysqldf=lambdaq: sqldf(q, globals())
现在,我们可以使用这个函数在我们的pandas dataframe上运行任何SQL查询。下面是不等连接,我们希望使用可读性更强的SQL格式。
q="""SELECT A.*,B.TransactionDt,B.SalesFROMofferDf AINNER JOINtransactionDf BONA.Item = B.Item ANDA.StartDt <= B.TransactionDt ANDA.EndDt >= B.TransactionDt;"""pandaSQL_solution=pysqldf(q)
结果是一个我们所期望的panda Dataframe。索引已经自动为我们重置了,不像以前那样需要手动操作。
警告
虽然PandaSQL函数允许我们在我们的panda数据框架上运行SQL查询,并且在某些情况下是一个非常好的工具,但是它的性能不如纯panda语法。
当我们用可读性更强的PandaSQL为pandas计时时,我们发现PandaSQL花费的时间大约是原生pandas的10倍。
结论
虽然PandaSQL库的性能不如本地的panda,但当我们想进行特别分析时,它是对我们的数据分析工具箱的一个很好的补充,而且对于那些更习惯使用SQL查询的人来说。
想要更深入地了解这篇文章的代码,请访问我的GitHub知识库,在那里你可以找到这篇文章和我所有的文章的代码。
https://github.com/MLWhiz/data_science_blogs/tree/master/pandasql
译者注:我一直在寻找能够使用sql处理pandas的dataframe的解决方案,pandasSQL在这这方面起到了很好的开端,虽然他的性能还不足以在生产环境中使用,但是我们再进行EDA和数据分析等一次性的操作的时候完全可以使用sql替代复杂的pandas的查询语法。所以如果你跟我一样,对SQL非常熟悉,并且厌倦了pandas的复杂语法,pandasSQL是一个很好的解决方案