Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 获取PySpark中窗口上与某些条件匹配的第一行_Python_Apache Spark_Pyspark - Fatal编程技术网

Python 获取PySpark中窗口上与某些条件匹配的第一行

Python 获取PySpark中窗口上与某些条件匹配的第一行,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,举个例子,假设我们有一个如下的用户操作流: 从pyspark.sql导入* spark=SparkSession.builder.appName('test').master('local[8]).getOrCreate() df=spark.sparkContext.parallelize([ 行(用户=1,操作=1,时间=1), 行(用户=1,操作=1,时间=2), 行(用户=2,操作=1,时间=3), 行(用户=1,操作=2,时间=4), 行(用户=2,操作=2,时间=5), 行(用户=2

举个例子,假设我们有一个如下的用户操作流:

从pyspark.sql导入*
spark=SparkSession.builder.appName('test').master('local[8]).getOrCreate()
df=spark.sparkContext.parallelize([
行(用户=1,操作=1,时间=1),
行(用户=1,操作=1,时间=2),
行(用户=2,操作=1,时间=3),
行(用户=1,操作=2,时间=4),
行(用户=2,操作=2,时间=5),
行(用户=2,操作=2,时间=6),
行(用户=1,操作=1,时间=7),
行(用户=2,操作=1,时间=8),
]).toDF()
df.show()
数据帧看起来像:

+----+------+----+
|user|action|time|
+----+------+----+
|   1|     1|   1|
|   1|     1|   2|
|   2|     1|   3|
|   1|     2|   4|
|   2|     2|   5|
|   2|     2|   6|
|   1|     1|   7|
|   2|     1|   8|
+----+------+----+
然后,我想在每一行中添加一列
next\u alt\u time
,给出用户在以下行中更改动作类型的时间。对于上述输入,输出应为:

+----+------+----+-------------+
|user|action|time|next_alt_time|
+----+------+----+-------------+
|   1|     1|   1|            4|
|   1|     1|   2|            4|
|   2|     1|   3|            5|
|   1|     2|   4|            7|
|   2|     2|   5|            8|
|   2|     2|   6|            8|
|   1|     1|   7|         null|
|   2|     1|   8|         null|
+----+------+----+-------------+
我知道我可以创建如下窗口:

wnd = Window().partitionBy('user').orderBy('time').rowsBetween(1, Window.unboundedFollowing)

但是我不知道如何在窗口上施加条件,并在上面定义的窗口上选择与当前行具有不同操作的第一行。

下面介绍如何执行。Spark无法保持数据帧的顺序,但如果您逐个检查行,则可以确认它给出了预期的答案:

from pyspark.sql import Row
from pyspark.sql.window import Window
import pyspark.sql.functions as F

df = spark.sparkContext.parallelize([
    Row(user=1, action=1, time=1),
    Row(user=1, action=1, time=2),
    Row(user=2, action=1, time=3),
    Row(user=1, action=2, time=4),
    Row(user=2, action=2, time=5),
    Row(user=2, action=2, time=6),
    Row(user=1, action=1, time=7),
    Row(user=2, action=1, time=8),
]).toDF()

win = Window().partitionBy('user').orderBy('time')

df = df.withColumn('new_action', F.lag('action').over(win) != F.col('action'))
df = df.withColumn('new_action_time', F.when(F.col('new_action'), F.col('time')))
df = df.withColumn('next_alt_time', F.first('new_action', ignorenulls=True).over(win.rowsBetween(1, Window.unboundedFollowing)))

df.show()

+----+------+----+----------+---------------+-------------+
|user|action|time|new_action|new_action_time|next_alt_time|
+----+------+----+----------+---------------+-------------+
|   1|     1|   1|      null|           null|            4|
|   1|     1|   2|     false|           null|            4|
|   1|     2|   4|      true|              4|            7|
|   1|     1|   7|      true|              7|         null|
|   2|     1|   3|      null|           null|            5|
|   2|     2|   5|      true|              5|            8|
|   2|     2|   6|     false|           null|            8|
|   2|     1|   8|      true|              8|         null|
+----+------+----+----------+---------------+-------------+


预计产量??非常感谢。重新排序的数据帧实际上使计算更加清晰。我没有想到使用滞后,但现在我发现使用它来检测变化是很自然的。