Pyspark 按与同一数据帧的其他行相对应的数据选择行

Pyspark 按与同一数据帧的其他行相对应的数据选择行,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我正在努力选择数据帧的行。选择取决于同一数据帧内的数据 我的数据集如下所示: from pyspark.sql.session import SparkSession sc = SparkSession.builder.getOrCreate() columns = ['Id', 'ActorId', 'EventId', 'Time'] vals = [(3, 3, 'START', '2020-06-22'), (4, 3, 'END', '2020-06-24')

我正在努力选择数据帧的行。选择取决于同一数据帧内的数据

我的数据集如下所示:

from pyspark.sql.session import SparkSession
sc = SparkSession.builder.getOrCreate()
columns = ['Id', 'ActorId', 'EventId', 'Time']
vals = [(3,  3, 'START', '2020-06-22'), 
        (4,  3, 'END',   '2020-06-24'), 
        (5,  3, 'OTHER', '2019-01-15'), 
        (6,  3, 'OTHER', '2020-07-24'), 
        (7,  3, 'OTHER', '2020-06-23'), 
        (8,  4, 'START', '2018-01-15'), 
        (9,  4, 'END',   '2019-01-14'), 
        (10, 4, 'OTHER', '2018-11-14')]
events = sc.createDataFrame(vals,columns)
events.show()
其结果是:

+---+-------+-------+----------+
| Id|ActorId|EventId|      Time|
+---+-------+-------+----------+
|  3|      3|  START|2020-06-22|
|  4|      3|    END|2020-06-24|
|  5|      3|  OTHER|2019-01-15|
|  6|      3|  OTHER|2020-07-24|
|  7|      3|  OTHER|2020-06-23|
|  8|      4|  START|2018-01-15|
|  9|      4|    END|2019-01-14|
| 10|      4|  OTHER|2018-11-14|
+---+-------+-------+----------+
(请记住,这只是一个示例->数据提取)

我想查找EventId==OTHER的所有行,其中时间不在同一ActorId的开始和结束事件之间。 结果应该如下所示:

+---+-------+-------+----------+
| Id|ActorId|EventID|      Time|
+---+-------+-------+----------+
|  5|      3|  OTHER|2019-01-15|
|  6|      3|  OTHER|2020-07-24|
+---+-------+-------+----------+
谢谢你的帮助

 val res = vals
  .filter('EventId.equalTo("OTHER"))
  .filter('ActorId.equalTo(3))
  .filter(!'Time.between("2020-06-01","2020-06-25"))

  res.show(false)
//  +---+-------+-------+----------+
//  |Id |ActorId|EventId|Time      |
//  +---+-------+-------+----------+
//  |5  |3      |OTHER  |2019-01-15|
//  |6  |3      |OTHER  |2020-07-24|
//  +---+-------+-------+----------+


这将解决您的问题-下面的代码中只有一个假设,即eventId列的开始和结束将始终出现在每组的第一行和第二行

_w = W.partitionBy('ActorId').orderBy('ActorId')


events = events.withColumn('start_date', F.first('Time').over(_w))
events = events.withColumn('row_num', F.row_number().over(_w))
events = events.withColumn('end_date', F.when(F.col('row_num') == F.lit('2'), F.col('Time')))
events = events.withColumn('end_date', F.coalesce(F.when(F.col('row_num') == F.lit('2'), F.col('Time')), F.min('end_date').over(_w)))
events = events.withColumn('passed_col', F.when(
  (
    ((F.col('Time').cast(T.TimestampType()) > F.col('start_date').cast(T.TimestampType())) & (F.col('Time').cast(T.TimestampType()) > F.col('end_date').cast(T.TimestampType()))) |
                                                                                            
    (
      (F.col('Time').cast(T.TimestampType()) < F.col('start_date').cast(T.TimestampType()))
                                                & (F.col('Time').cast(T.TimestampType()) < F.col('end_date').cast(T.TimestampType())))),F.lit("Passed")))

events = events.select('Id', 'ActorId', 'EventId', 'Time', 'passed_col')
events.show() 

+---+-------+-------+----------+----------+
| Id|ActorId|EventId|      Time|passed_col|
+---+-------+-------+----------+----------+
|  3|      3|  START|2020-06-22|      null|
|  4|      3|    END|2020-06-24|      null|
|  5|      3|  OTHER|2019-01-15|    Passed|
|  6|      3|  OTHER|2020-07-24|    Passed|
|  7|      3|  OTHER|2020-06-23|      null|
|  8|      4|  START|2018-01-15|      null|
|  9|      4|    END|2019-01-14|      null|
| 10|      4|  OTHER|2018-11-14|      null|
+---+-------+-------+----------+----------+

谢谢你的回答。我没有提到我的表包含更多的数据,有更多的参与者和事件,具体时间不匹配。我正在寻找一种更普遍的方法,即起点和终点值是否始终保持在第一和第二位置?重要的问题!不幸的是没有,但我添加了一个版本的代码作为注释,这应该可以确保顺序不重要谢谢你的回答!那帮了大忙!最后,我通过以下方式选择开始和结束日期:events=events.withColumn('START_Date',F.when('EventId')==F.lit('START'),F.col('Time'))events=events.withColumn('END_Date',F.when('F.col('EventId')==F.lit('END'),F.coll('Time')),这样顺序就不会有任何区别。withColumn()将迭代每一行,因此,在您的datafram中,开始和结束出现4次,因此已记入贷方的新列将在不匹配的地方产生空值。示例行:3、4、5 6正确!我只是用它来代替你的前三行。然后我像你一样使用了coalesce函数,只是我没有创建行号,而是使用了EventId,比如:events=events.withColumn('start_-date',F.coalesce(F.when(F.col('EventId')==F.lit('start')、F.col('Time')、F.min('start_-date)。over('w)))events=events.withColumn('end_-date',F.when(F.col('EventId'))==F.lit('END')、F.col('Time')、F.max('END\u date')。超过('u w)))
_w = W.partitionBy('ActorId').orderBy('ActorId')


events = events.withColumn('start_date', F.first('Time').over(_w))
events = events.withColumn('row_num', F.row_number().over(_w))
events = events.withColumn('end_date', F.when(F.col('row_num') == F.lit('2'), F.col('Time')))
events = events.withColumn('end_date', F.coalesce(F.when(F.col('row_num') == F.lit('2'), F.col('Time')), F.min('end_date').over(_w)))
events = events.withColumn('passed_col', F.when(
  (
    ((F.col('Time').cast(T.TimestampType()) > F.col('start_date').cast(T.TimestampType())) & (F.col('Time').cast(T.TimestampType()) > F.col('end_date').cast(T.TimestampType()))) |
                                                                                            
    (
      (F.col('Time').cast(T.TimestampType()) < F.col('start_date').cast(T.TimestampType()))
                                                & (F.col('Time').cast(T.TimestampType()) < F.col('end_date').cast(T.TimestampType())))),F.lit("Passed")))

events = events.select('Id', 'ActorId', 'EventId', 'Time', 'passed_col')
events.show() 

+---+-------+-------+----------+----------+
| Id|ActorId|EventId|      Time|passed_col|
+---+-------+-------+----------+----------+
|  3|      3|  START|2020-06-22|      null|
|  4|      3|    END|2020-06-24|      null|
|  5|      3|  OTHER|2019-01-15|    Passed|
|  6|      3|  OTHER|2020-07-24|    Passed|
|  7|      3|  OTHER|2020-06-23|      null|
|  8|      4|  START|2018-01-15|      null|
|  9|      4|    END|2019-01-14|      null|
| 10|      4|  OTHER|2018-11-14|      null|
+---+-------+-------+----------+----------+
events = events.filter(F.col('passed_col') == F.lit('Passed')).select('Id', 'ActorId', 'EventId', 'Time', 'passed_col')
events.show()

+---+-------+-------+----------+----------+
| Id|ActorId|EventId|      Time|passed_col|
+---+-------+-------+----------+----------+
|  5|      3|  OTHER|2019-01-15|    Passed|
|  6|      3|  OTHER|2020-07-24|    Passed|
+---+-------+-------+----------+----------+