Python 基于数据帧的火花重叠算法
给定具有以下字段的数据源:product\u id-product-start\u time-end\u time 我正在尝试使用Dataframe函数,基于开始时间和结束时间构建捕获同一产品重叠记录的逻辑Python 基于数据帧的火花重叠算法,python,apache-spark,pyspark,apache-spark-sql,Python,Apache Spark,Pyspark,Apache Spark Sql,给定具有以下字段的数据源:product\u id-product-start\u time-end\u time 我正在尝试使用Dataframe函数,基于开始时间和结束时间构建捕获同一产品重叠记录的逻辑 ------------------------------------------------ | product_id | product | start_time | end_time | ------------------------------------------------
------------------------------------------------
| product_id | product | start_time | end_time |
------------------------------------------------
| 1 | bottle | 2 | 4 |
| 2 | bottle | 3 | 5 |
| 3 | bottle | 2 | 3 |
| 4 | bottle | 6 | 7 |
| 1 | can | 2 | 4 |
| 2 | can | 5 | 6 |
| 3 | can | 2 | 4 |
我想接收输出
-------------------------------------------------------------------------------------------------
| product_id_a | product_id_b | product | start_time_a | end_time_a | start_time_b | end_time_b |
-------------------------------------------------------------------------------------------------
| 1 | 2 | bottle | 2 | 4 | 3 | 5 |
| 1 | 3 | bottle | 2 | 4 | 2 | 3 |
因为瓶子_1与瓶子_2和瓶子_3有重叠时间,如果满足以下条件,则两条记录重叠:
最大a.开始时间,b.开始时间<最小a.结束时间,b.结束时间
!a、 开始时间==b.开始时间和a.结束时间==b.结束时间
a、 开始时间!=b、 开始| |结束|时间!=b、 结束时间
其中,最后两个条件仅规定我对开始时间和结束时间相等的情况不感兴趣,例如,can_1和can_3不在预期结果中,即使它们具有相同的开始时间和结束时间
因为问题的结构很容易想到使用RDD的MapReduce解决方案,但我对使用Dataframes的解决方案感兴趣
提示:使用groupBy.agg是否有可能指定达到所述逻辑的有趣条件
如需进一步解释,请随时询问
不重复
不幸的是,在报告的答案中使用了F.lag,在我的情况下,这不是一个足够好的条件:F.lag仅使用与先前记录的比较,但在报告的示例中,由于瓶_1不是连续记录,因此不会报告为与瓶_3重叠,因此无法按预期工作每个条件都可以直接转换为SQL 从pyspark.sql.functions导入列、最小列、最大列 条件1= 最棒的可乐开始时间,可乐开始时间< 最短时间,最短时间 条件2=~ cola.start_time==colb.start_time& cola.end_time==colb.end_time 条件3= 可乐。开始时间!=colb.开始时间| 可乐。结束时间!=结束时间 所以你可以加入并过滤
(df.alias("a").join(df.alias("b"), ["product"]).filter(cond1 & cond2 & cond3))
试试这个:
df.joincloneDf,$label.where$label!==$标签1.其中$min<$max1.其中$min1<$max.show
您需要对数据帧进行笛卡尔积来检查,如果行重叠,您可以根据需要映射它们。当然,您需要省略self-两个相同的行重叠
整个代码:
val df=SparkEmbedded.ss.createDataFrameSeq
1, 2, 5,
2, 4, 7,
3, 6, 9
.toDFproduct_id,最小值,最大值
导入SparkEmbedded.ss.implicits_
val cloneDf=df.selectdf.columns.mapcol:_*
.使用列重命名的产品标识,产品标识1
.withColumnRenamedmin,min1
.withColumnRenamedmax,max1
交叉连接
。其中$product\U id<$product\U id1
。其中$min<$max1
。其中$min1<$max.show
为了清楚起见,我将where子句拆分
结果是:
+-----+---+---+------+----+----+
|label|min|max|label1|min1|max1|
+-----+---+---+------+----+----+
| 1| 2| 5| 2| 4| 7|
| 2| 4| 7| 3| 6| 9|
+-----+---+---+------+----+----+
这个例子在Scala中,但是Python有类似的API。基于@Andronicus,我在纯Python中提出了这种方法
有必要将数据帧与他自己连接起来,以检查行是否重叠。当然,您需要省略self,条件为df.product\u id谢谢!您的解决方案和@user11013893都帮助我解决了问题!您的解决方案中的where$label<$label1帮助我避免了重复的结果,而另一个提供了更有趣的函数。可能交叉连接不是必需的:基于产品的普通内部连接(参见示例)就足够了。我不明白为什么我的问题被否决了,我对你的答案投了赞成票。但我认为您的答案在使用<条件where$label<$label1时更有用。我接受你的建议。为了提高答案的可读性,你能编辑你的帖子,让它更接近我报道的例子吗?因此,将where$label<$label1更改为where$product\u id<$product\u id1,基于产品的连接。。。因此我建议将python代码放在单独的答案中,因为它完全改变了编程风格。Scala是我用Java专业开发的完美之选;>