分别使用SQL和Python实现人流查询,考验逻辑思维能力的时候到了,也可以回顾一下SQL和Python的写法,所以决定先写这篇文章。通过这道题,我们会发现,在分析工作中,最重要的能力就是逻辑思维。程序只是实现逻辑的工具。没有逻辑思维能力,程序就一无是处。而且,虽然实现一个结果的逻辑有很多种,但是好的逻辑会让我们的程序更加简洁、可观察、高效。下面是根据自己的理解总结的两类实现逻辑。相信一些大牛的脑子里肯定会有更好的逻辑!案例介绍案例来自LeetCode。这样的需求在时间序列数据中还是比较常见的。某市体育馆每天的人流量记录在体育馆表的三列信息中:序号(id)、日期(visit_date)、人流量(people)。找至少三个连续的人流量不低于100的记录。最简单的思路分析肯定是在球场表上进行三个笛卡尔积连接,但是这种方法在数据量大的时候不可取,并且它不可概括(例如,要求应更改为至少连续十行)。网上还流传着阿里的编程规范——禁止超过三张表的连接。总之,这种思路不是我们应该采用的,我们需要寻找其他的思路。(1)构造等差数列从上图我们可以发现一个规律,即原表和结果表中满足条件的数据区的行号都是等差数列,而这两个等差数列的差值是固定的。例如序列A1和B1的差为1;序列A2和B2的差值是2,只要保证等差数列在各个区域的差值不相等,那么我们就可以通过过滤差值出现的次数来过滤满足条件的区域。比如差异2出现4次,满足条件,那么差异对应的记录就是我们需要的数据。除了通过行号构造差值的方式,还有其他的方式,大家可以考虑一下。(2)数据分片从图中可以看出,if_true是一个辅助列,表示是否满足条件,1为True,0为False。我们要选择满足条件的区域。通过对0列进行切片,得到不同长度的小数列全为1,根据每个小数列的长度过滤满足条件的区域。图中得到长度为a和b的序列,通过计算序列的长度找到满足条件的区域。程序实现上一节我们选择了两种思路,其中Python可以实现两种思路,SQL可以实现第一种思路。本节中,第一个思路用SQL实现,第二个思路用Python实现。(1)SQLselectid,visit_date,peoplefrom(selectt2.*,count(1)over(partitionbyrn2)rn3from(selectt1.*,rn1-row_number()over(orderbyvisit_date)rn2from(select*,row_number()over()asrn1fromstadiumorderbyvisit_date)t1#t1表将日期按升序排序生成行号wherepeople>=100)t2#t2表过滤不低于100人的数据,用原行号减去新生成的行号得到差值where1=1)t3#t3表格统计每一类差异出现的次数wheren3>2#筛选频率大于2的数据为需要的数据。因为实际表中的ID几乎不是连续的数字,所以为了保证泛化,先生成行。编号,这样您就不必依赖于ID。另外,也可以通过用户变量等方式实现,大家可以试着想一想。(2)Pythonimportpandasaspddt=pd.DataFrame({"id":range(1,9),"visit_date":pd.date_range(start="2017-01-01",periods=8),"people":[10,109,150,99,145,1455,199,188]})dt["col1"]=dt["people"].apply(lambdax:1ifx>=100else0)#生成的人数是否不小于100newcolumndt['counter']=(dt["col1"]==0).cumsum()#根据col1列是否为0计算累加和,标记每个连续区域dt=dt[dt["col1"]!=0]#淘汰人数低于100条记录gb=dt.groupby("counter")["id"].count()#统计每个标签值出现的次数result=dt[dt["counter"].isin(gb[gb>2].index)]#过滤符合条件的数据。这里需要注意一件事。如果直接将col1列转成字符串,然后按0分片,虽然可以找到满足条件的区域个数和长度,但是很难找到具体的区域。.split_col1="".join([str(i)foriindt["col1"]]).split("0")本来是沿用了这个思路,但是发现在查找与原列表中字符串匹配的长度的索引时,会比较麻烦,尤其是需要查找多个索引值的时候。但是这个思路还是很重要的,因为只计算一个连续区域的最大值会很简单。结论以上只是两个简单的逻辑。其实也有一些合乎逻辑的方法,但大部分在本质上都是类似的,本文就不一一列举了。至于有没有更高效的逻辑方法,就等大牛指点了。如果有朋友完整看过,你会发现一个简单的例子可以有多种实现方法。在自己写每一个方法的过程中,都是对已有知识的一种梳理和复习。
