Pandas 按24小时分区,并使用pyspark或panda进行聚合
我有每个设备的会话数据,如下所示 开始时间:设备连接时的时间戳 持续时间(秒):连接的时间 数据包:发送多少数据包 现在,我需要将每个设备分区的持续时间和数据包聚合(求和)24小时 例如: 第一次记录在案 设备A的时间从4月8日凌晨1:53开始,因此需要汇总所有设备(A)在24小时内的有效时间(截至4月9日凌晨1:53) 然后,设备A的下一个记录应该从4月9日上午4:27开始,因此需要汇总所有设备(A)在24小时内的有效时间,即到4月10日上午4:27 及 对于每个设备,依此类推 预期产量 测试数据:Pandas 按24小时分区,并使用pyspark或panda进行聚合,pandas,apache-spark,pyspark,apache-spark-sql,pandas-groupby,Pandas,Apache Spark,Pyspark,Apache Spark Sql,Pandas Groupby,我有每个设备的会话数据,如下所示 开始时间:设备连接时的时间戳 持续时间(秒):连接的时间 数据包:发送多少数据包 现在,我需要将每个设备分区的持续时间和数据包聚合(求和)24小时 例如: 第一次记录在案 设备A的时间从4月8日凌晨1:53开始,因此需要汇总所有设备(A)在24小时内的有效时间(截至4月9日凌晨1:53) 然后,设备A的下一个记录应该从4月9日上午4:27开始,因此需要汇总所有设备(A)在24小时内的有效时间,即到4月10日上午4:27 及 对于每个设备,依此类推 预期产量
dftest = sc.parallelize([['A','2020-04-08T01:53:54.932000','Org1','wifi',60,372717],
['A','2020-04-08T02:40:38.661000','Org1','wifi',194,819040],
['A','2020-04-08T21:45:10.207000','Org1','wifi',8885,3449150],
['A','2020-04-09T00:15:28.838000','Org1','wifi',14770,3572589],
['A','2020-04-09T04:27:33.424000','Org1','remote',0,0],
['A','2020-04-09T04:29:25.189000','Org1','wifi',60,7495],
['A','2020-04-09T04:44:21.397000','Org1','remote',60,553356],
['A','2020-04-09T04:50:40.406000','Org1','wifi',60,662467],
['A','2020-04-10T00:00:50.636000','Org1','remote',0,72],
['A','2020-04-10T04:20:28.831000','Org1','remote',6,497],
['A','2020-04-10T04:31:35.336000','Org1','remote',0,22],
['B','2020-04-08T21:56:58.502000','Org2','remote',0,0],
['B','2020-04-08T22:01:19.534000','Org2','wifi',0,0],
['B','2020-04-08T22:10:15.891000','Org2','wifi',60,187891],
['B','2020-04-08T22:16:41.499000','Org2','wifi',1620,207674],
['B','2020-04-09T01:55:02.772000','Org2','wifi',360,426232],
['B','2020-04-09T02:03:32.735000','Org2','wifi',60,374827],
['B','2020-04-09T02:06:16.509000','Org2','wifi',60,386518],
['B','2020-04-09T02:13:33.497000','Org2','remote',60,373609],
['B','2020-04-09T02:17:19.176000','Org2','wifi',133,400417],
['B','2020-04-10T23:10:15.654000','Org2','remote',0,212],
['B','2020-04-10T23:10:41.749000','Org2','remote',1,285]
]).toDF(("deviceId","time-started","OrgId","type","duration","packet"))
dftest.show()
对于您的情况,您的下一个
24小时
取决于上一个的结束时间
,以及最后一个日期之后的日期
,因此我们不能仅用窗口函数来表达此逻辑。我将pandas的求和计算解耦(因为它会很慢),并使用内置的spark函数来获得求和,pandas udaf基本上为我们提供了所需的日期组
,我们对它们进行过滤
以获得所需的结果
迭代是获取24小时分段的唯一方法,因此您也可以使用简单的udf,但熊猫矢量化udaf允许我们在小组(基于id)上表达我们的逻辑,因此应该更好udaf(spark2.3+)
import pandas as pd
from pyspark.sql.functions import pandas_udf, PandasUDFType
from pyspark.sql import functions as F
from pyspark.sql.window import Window
w=Window().partitionBy("deviceId").orderBy(F.col("time-started").cast("long")).rangeBetween(Window.currentRow,24*60*60)
df2=df.withColumn("time-started", F.to_timestamp("time-started", "yyyy-MM-dd'T'HH:mm:ss"))\
.withColumn("time-started-2", F.col("time-started"))\
.withColumn("duration", F.sum("duration").over(w))\
.withColumn("packet", F.sum("packet").over(w))
@pandas_udf(df2.schema, PandasUDFType.GROUPED_MAP)
def grouped_map(df1):
start=df1.loc[0, 'time-started']
for i in range(1, len(df1)):
if start + pd.Timedelta(days=1)>df1.loc[i,'time-started']:
df1.loc[i,'time-started']=start
else:
start=df1.loc[i,'time-started']
return df1
df2.groupby('deviceId').apply(grouped_map)\
.filter(F.col("time-started-2")==F.col("time-started"))\
.drop("time-started-2")\
.orderBy("deviceId")\
.show()
#+--------+-------------------+-----+------+--------+-------+
#|deviceId| time-started|OrgId| type|duration| packet|
#+--------+-------------------+-----+------+--------+-------+
#| A|2020-04-08 01:53:54| Org1| wifi| 23909|8213496|
#| A|2020-04-09 04:27:33| Org1|remote| 186|1223887|
#| A|2020-04-10 04:31:35| Org1|remote| 0| 22|
#| B|2020-04-08 21:56:58| Org2|remote| 2353|2357168|
#| B|2020-04-10 23:10:15| Org2|remote| 1| 497|
#+--------+-------------------+-----+------+--------+-------+
你也可以看一看。建议的解决方案是使用foldleft特性的scala udf。我认为udaf是一个更好的选择。24小时分区装置意味着第一个a
开始于8thApril 1:53 AM
,第二个开始于2020-04-09T04:27
,2020-04-10T04:20处的3rd
而不是4:31
,因为第一个值来自8th 1:53-9th 1:53
,第二个值来自下一个值,即9th 4:27到10th 1:53
,第三个值来自下一个值,即10th 4:27
,,,……不是吗?@raviteja我认为您的24小时窗口对于spark window func来说有点过于动态,因为它取决于上一个窗口的末尾来计算下一个窗口,因此建议使用spark window函数和pandas udaf的组合。@MohammadMurtazaHashmi您可以吗elaborate@RaviTeja我刚刚发布了,如果有帮助的话