Python 使用Windows的PySpark多列

Python 使用Windows的PySpark多列,python,pyspark,apache-spark-sql,pyspark-dataframes,Python,Pyspark,Apache Spark Sql,Pyspark Dataframes,我有一个数据框,如下所示: |id |date_1 |date_2 | +---+----------+-----------+ |0 |2017-01-21|2017-04-01 | |1 |2017-01-22|2017-04-24 | |2 |2017-02-23|2017-04-30 | |3 |2017-02-27|2017-04-30 | |4 |2017-04-23|2017-05-27 | |5 |2017-04-29|2017-06-30 | |6

我有一个数据框,如下所示:

|id |date_1    |date_2     |
+---+----------+-----------+
|0  |2017-01-21|2017-04-01 |
|1  |2017-01-22|2017-04-24 |
|2  |2017-02-23|2017-04-30 |
|3  |2017-02-27|2017-04-30 |
|4  |2017-04-23|2017-05-27 |
|5  |2017-04-29|2017-06-30 |
|6  |2017-06-13|2017-07-05 |
|7  |2017-06-13|2017-07-18 |
|8  |2017-06-16|2017-07-19 |
|9  |2017-07-09|2017-08-02 |
|10 |2017-07-18|2017-08-07 |
|11 |2017-07-28|2017-08-11 |
|12 |2017-07-28|2017-08-13 |
|13 |2017-08-04|2017-08-13 |
|14 |2017-08-13|2017-08-13 |
|15 |2017-08-13|2017-08-13 |
|16 |2017-08-13|2017-08-25 |
|17 |2017-08-13|2017-09-10 |
|18 |2017-08-31|2017-09-21 |
|19 |2017-10-03|2017-09-22 |
+---+----------+-----------+
我知道有很多方法可以使用不同的pyspark API实现我的要求,但是我想使用
窗口
API来完成以下任务

在任何其他情况下,它本质上是一个双for循环

对于
date_1
中的每个日期,查看
date_2
中相同行或后续行中的每个日期,并计算差异出现在一周、一个月内的次数,…(时间范围不相关,但为了一致性起见,让我们以周为准)。使用这些结果添加另一个具有计数的列


挑战是获得正确的<代码>窗口< /代码>(s)组合来考虑两个日期列。

< P>如果数据流中的每一行X都正确地理解问题的作者,我们想从该行开始的所有行(按例如“代码> ID < /代码>排序”),并且对于每一行这样的Y,比较X.DATEY1与Y.DATEY2。X.date_1和Y.date_2之间的差值小于例如1周的行数Y应作为列添加到行X(例如X.result)

不幸的是,窗口功能没有提供访问
X.date_1
内部窗口功能的功能,因此无法使用窗口功能实现

这似乎非常类似于作者试图为博士后做类似的事情

但是有一种方法可以通过一点欺骗来实现,即为数组中的每一行“具体化”窗口帧,然后执行所需的操作。不确定在您看来这是否算数,但这是使用windowapi解决问题的唯一方法。一个可能的解决方案可能是这样的(假设我们要计算不早于X w.r.t
id的行数Y,其中
Y.date\u 2
介于
X.date\u 1
X.date\u 1+7天之间):

结果是:

+---+----------+----------+------+
| id|    date_1|    date_2|result|
+---+----------+----------+------+
|  0|2017-01-21|2017-04-01|     0|
|  1|2017-01-22|2017-04-24|     0|
|  2|2017-02-23|2017-04-30|     0|
|  3|2017-02-27|2017-04-30|     0|
|  4|2017-04-23|2017-05-27|     0|
|  5|2017-04-29|2017-06-30|     0|
|  6|2017-06-13|2017-07-05|     0|
|  7|2017-06-13|2017-07-18|     0|
|  8|2017-06-16|2017-07-19|     0|
|  9|2017-07-09|2017-08-02|     0|
| 10|2017-07-18|2017-08-07|     0|
| 11|2017-07-28|2017-08-11|     0|
| 12|2017-07-28|2017-08-13|     0|
| 13|2017-08-04|2017-08-13|     0|
| 14|2017-08-13|2017-08-13|     2|
| 15|2017-08-13|2017-08-13|     1|
| 16|2017-08-13|2017-08-25|     0|
| 17|2017-08-13|2017-09-10|     0|
| 18|2017-08-31|2017-09-21|     0|
| 19|2017-10-03|2017-09-22|     0|
+---+----------+----------+------+

也许这是有帮助的-

加载提供的测试数据
val数据=
"""
|id |日期| 1 |日期| 2
|0  |2017-01-21|2017-04-01
|1  |2017-01-22|2017-04-24
|2  |2017-02-23|2017-04-30
|3  |2017-02-27|2017-04-30
|4  |2017-04-23|2017-05-27
|5  |2017-04-29|2017-06-30
|6  |2017-06-13|2017-07-05
|7  |2017-06-13|2017-07-18
|8  |2017-06-16|2017-07-19
|9  |2017-07-09|2017-08-02
|10 |2017-07-18|2017-08-07
|11 |2017-07-28|2017-08-11
|12 |2017-07-28|2017-08-13
|13 |2017-08-04|2017-08-13
|14 |2017-08-13|2017-08-13
|15 |2017-08-13|2017-08-13
|16 |2017-08-13|2017-08-25
|17 |2017-08-13|2017-09-10
|18 |2017-08-31|2017-09-21
|19 |2017-10-03|2017-09-22
“.stripMargin”
val stringDS=data.split(System.lineSeparator())
.map(\\\\\).map(\.replaceAll(“^[\t]+\\t]+$”,“).mkString(“,”)
.toSeq.toDS()
val df=spark.read
.期权(“sep”、“、”)
.选项(“推断模式”、“真”)
.选项(“标题”、“正确”)
.选项(“空值”、“空值”)
.csv(stringDS)
df.show(假)
df.printSchema()
/**
* +---+-------------------+-------------------+
*| id |日期| 1 |日期| 2|
* +---+-------------------+-------------------+
* |0  |2017-01-21 00:00:00|2017-04-01 00:00:00|
* |1  |2017-01-22 00:00:00|2017-04-24 00:00:00|
* |2  |2017-02-23 00:00:00|2017-04-30 00:00:00|
* |3  |2017-02-27 00:00:00|2017-04-30 00:00:00|
* |4  |2017-04-23 00:00:00|2017-05-27 00:00:00|
* |5  |2017-04-29 00:00:00|2017-06-30 00:00:00|
* |6  |2017-06-13 00:00:00|2017-07-05 00:00:00|
* |7  |2017-06-13 00:00:00|2017-07-18 00:00:00|
* |8  |2017-06-16 00:00:00|2017-07-19 00:00:00|
* |9  |2017-07-09 00:00:00|2017-08-02 00:00:00|
* |10 |2017-07-18 00:00:00|2017-08-07 00:00:00|
* |11 |2017-07-28 00:00:00|2017-08-11 00:00:00|
* |12 |2017-07-28 00:00:00|2017-08-13 00:00:00|
* |13 |2017-08-04 00:00:00|2017-08-13 00:00:00|
* |14 |2017-08-13 00:00:00|2017-08-13 00:00:00|
* |15 |2017-08-13 00:00:00|2017-08-13 00:00:00|
* |16 |2017-08-13 00:00:00|2017-08-25 00:00:00|
* |17 |2017-08-13 00:00:00|2017-09-10 00:00:00|
* |18 |2017-08-31 00:00:00|2017-09-21 00:00:00|
* |19 |2017-10-03 00:00:00|2017-09-22 00:00:00|
* +---+-------------------+-------------------+
*
*根
*|--id:integer(nullable=true)
*|--date_1:时间戳(nullable=true)
*|--date_2:时间戳(nullable=true)
*/
计算差异(日期1-2)在一周内出现的次数
//每周
val weekDiff=7
val w=窗口.orderBy(“id”、“日期1”、“日期2”)
.rangeBetween(Window.currentRow,Window.unboundedFollowing)
df.带列(“计数”,总和(

何时(日期差异($“日期1”,“日期2”)你能提供你想要得到什么的示例输出吗?你的单词描述有点模棱两可。从它现在给我的感觉来看,它听起来更像是你只想在
date\u 1
上有一个窗口。好吧,我想我不知怎么地把
后续行
理解为
后续行
作为单数而不是复数。所以就你的qu而言估计-您需要按
date\u 1
还是按
id
订购“后续”?这似乎不是作者所问的-他们说他们想在给定行之后计算行数,其中日期\u 2在原始行的日期\u 1之内(即,在X行的窗口框中,与原始X行的日期_1相比,每行Y应具有Y.date_2,而不是同一行的日期_1日期_2的来源).我将等待作者的确认。这是我从描述到现在为止的理解。无论如何,我准备根据authorFair的反馈将此初始解决方案更改为更具体的解决方案。这是绝对的
+---+----------+----------+------+
| id|    date_1|    date_2|result|
+---+----------+----------+------+
|  0|2017-01-21|2017-04-01|     0|
|  1|2017-01-22|2017-04-24|     0|
|  2|2017-02-23|2017-04-30|     0|
|  3|2017-02-27|2017-04-30|     0|
|  4|2017-04-23|2017-05-27|     0|
|  5|2017-04-29|2017-06-30|     0|
|  6|2017-06-13|2017-07-05|     0|
|  7|2017-06-13|2017-07-18|     0|
|  8|2017-06-16|2017-07-19|     0|
|  9|2017-07-09|2017-08-02|     0|
| 10|2017-07-18|2017-08-07|     0|
| 11|2017-07-28|2017-08-11|     0|
| 12|2017-07-28|2017-08-13|     0|
| 13|2017-08-04|2017-08-13|     0|
| 14|2017-08-13|2017-08-13|     2|
| 15|2017-08-13|2017-08-13|     1|
| 16|2017-08-13|2017-08-25|     0|
| 17|2017-08-13|2017-09-10|     0|
| 18|2017-08-31|2017-09-21|     0|
| 19|2017-10-03|2017-09-22|     0|
+---+----------+----------+------+