第一次发文,对最近写的代码总结一下。不当之处多多包含,有好方法请多多指教。
1、判断连续3条数据的某一列的值是否相同。
一开始我使用的是sparksql来做的,做法很简单:首先对eA表数据添加一个row_number()作为唯一标识id,然后自己关联自己,写法如下,
select a.id, a.status,b.status,c.status
from tkdw a
left join trackdw b on a.id=b.id-1
left join trackdw c on a.id=c.id-2
这样就能将连续三条数据的status字段都放在一条数据中了。代码还包含了很多比较复杂的业务逻辑,也都是用sql方式实现的,这里就不列出来了。这种sql方式写起来简单,但是正真在集群上跑由于join的存在会相当耗费资源,数据量比较小的情况下(几百兆),在集群上跑没有问题,但当数据量大到30多G时,集群跑不出结果。
改变思路。首先将同一个vid的数据放在一起:
tsnew = data_use_df.groupby('_1').agg(collect_list(struct(data_use_df['_2'],data_use_df['_3'],data_use_df['_4'],data_use_df['_5'],data_use_df['_6'])).alias("locations"))
‘_1’是vid,就是商品的id。通过商品id进行groupby,然后将通过agg(collect_list(...))将某id商品的数据统统放在一起,形成一个list。也就是 (vid,list)这么一种格式。
[Row(_1=u'10603', locations=[Row(_2=0.0, _3=0, _4=0, _5=3378.0, _6=1523871553), Row(_2=0.0, _3=0, _4=0, _5=3378.0, _6=1523871553)]),
Row(_1=u'10777', locations=[Row(_2=1120.0, _3=1, _4=77, _5=36172.0, _6=1523873306), Row(_2=1148.0, _3=1, _4=81, _5=36159.0, _6=1523872753), Row(_2=1186.0, _3=1, _4=85, _5=36150.0, _6=1523872387), Row(_2=1186.0, _3=1, _4=85, _5=36150.0, _6=1523872387), Row(_2=1148.0, _3=1, _4=81, _5=36159.0, _6=1523872753), Row(_2=1120.0, _3=1, _4=77, _5=36172.0, _6=1523873306)]),
Row(_1=u'10994', locations=[Row(_2=909.0, _3=1, _4=12, _5=15394.0, _6=1523872863), Row(_2=700.0, _3=1, _4=35, _5=15394.0, _6=1523872360), Row(_2=699.0, _3=1, _4=24, _5=15394.0, _6=1523872363), Row(_2=700.0, _3=1, _4=20, _5=15394.0, _6=1523872366), Row(_2=700.0, _3=1, _4=35, _5=15394.0, _6=1523872360), Row(_2=699.0, _3=1, _4=24, _5=15394.0, _6=1523872363), Row(_2=700.0, _3=1, _4=20, _5=15394.0, _6=1523872366), Row(_2=909.0, _3=1, _4=12, _5=15394.0, _6=1523872863)])]
剩下的事情,打眼一看,是不是明了了?通过一个map就能搞定,当然map里的函数需要自己定义一下,比较冗长。。。
避免使用for循环,看看如何取相邻3条数据的某一字段吧。首先将list转成pandas的dataframe,举个例子
比如想取想取下一条的key1和再下一条的key1,看看这相邻的三个key1值是否相等,用pandas的dataframe的shift就可以方便搞定
shift(-1)取该字段下一条的数据,shift(-2)就是下移两条的数据,默认的shift()是取上一条的数据。这样我们就把需要的数据放在了同一条数据,判断起来就简单了。
整个的spark代码已经完成第二版了,今天测试一下跑30多G的数据。总觉得还是用sparksql更好,但还没细想如何优化,希望大神指教~~
谢谢!