Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.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
Apache spark 如果ID映射到窗口中的多个其他ID,则创建标志_Apache Spark_Pyspark - Fatal编程技术网

Apache spark 如果ID映射到窗口中的多个其他ID,则创建标志

Apache spark 如果ID映射到窗口中的多个其他ID,则创建标志,apache-spark,pyspark,Apache Spark,Pyspark,我试图创建一个标志,显示哪些id1值在任意窗口n上重复映射到id2(n=2)。例如,给定此数据帧: df = spark.createDataFrame( [("2010-03-10", "A", "X"), ("2010-03-10", "A", "Y"), ("2010-03-10", "B", "Z"),

我试图创建一个标志,显示哪些
id1
值在任意窗口
n
上重复映射到
id2
n=2
)。例如,给定此数据帧:

df = spark.createDataFrame(
[("2010-03-10", "A", "X"),
 ("2010-03-10", "A", "Y"),
 ("2010-03-10", "B", "Z"),
 ("2010-04-10", "A", "X"),
 ("2010-04-10", "A", "Y"),
 ("2010-04-10", "B", "Z"),
 ("2010-05-10", "A", "X"),
 ("2010-05-10", "A", "Y"),
 ("2010-05-10", "B", "Z"),
 ("2010-06-10", "A", "X"),
 ("2010-06-10", "B", "Z"),
 ("2010-07-10", "A", "X"),
 ("2010-07-10", "B", "Z")],
 ("date", "id1", "id2")
)
df.show()

+----------+---+---+
|      date|id1|id2|
+----------+---+---+
|2010-03-10|  A|  X|
|2010-03-10|  A|  Y|
|2010-03-10|  B|  Z|
|2010-04-10|  A|  X|
|2010-04-10|  A|  Y|
|2010-04-10|  B|  Z|
|2010-05-10|  A|  X|
|2010-05-10|  A|  Y|
|2010-05-10|  B|  Z|
|2010-06-10|  A|  X|
|2010-06-10|  B|  Z|
|2010-07-10|  A|  X|
|2010-07-10|  B|  Z|
+----------+---+---+
预期产出:

+----------+---+---+--------+
|      date|id1|id2|dup_flag|
+----------+---+---+--------+
|2010-03-10|  A|  X|       1|
|2010-03-10|  A|  Y|       1|
|2010-03-10|  B|  Z|       0|
|2010-04-10|  A|  X|       1|
|2010-04-10|  A|  Y|       1|
|2010-04-10|  B|  Z|       0|
|2010-05-10|  A|  X|       1|
|2010-05-10|  A|  Y|       1|
|2010-05-10|  B|  Z|       0|
|2010-06-10|  A|  X|       1|
|2010-06-10|  B|  Z|       0|
|2010-07-10|  A|  X|       0|
|2010-07-10|  B|  Z|       0|
+----------+---+---+--------+
其中,
dup_flag
是一个标志,指示id1是否在过去2个月的某个地方包含到
id2
的重复映射

也就是说,对于
id1
B
,它从不映射到
Z
以外的任何其他
id2
,因此它从不被标记为重复。
对于
id1
A
我们有重复的映射。在本例中,我将窗口大小设置为
2
,这意味着如果
A
在最多一个月后的窗口的任何日期内映射到多个
id2
(即当前月份以及上个月都应包含在窗口中),则它应收到一个标志。因此,
A
接收此标志直到
2010-07-10
,在这一时期,我们有一个由
2010-06-10
2010-07-10
组成的窗口,其中
A
不映射到多个
id2
(它只映射到该窗口中的
id2
X
).

解决这个问题的方法有些老套。实际上,您创建了一个基于范围而不是基于行的窗口,并在该窗口上执行
countdistinct
。不知何故,Spark不支持后者,因此我需要通过使用
size(collect\u set)
来绕过它,它本质上与
count distinct
相同。另外,Spark不支持按日期排序的基于范围的窗口,因此我需要将该列转换为整数类型,并使用一个神奇的数字2678400,它等于31天内的秒数

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

### initialize df as in the question
### df = ...

df = df.withColumn('date', F.col('date').cast('timestamp').cast('bigint'))
flag = (F.size(F.collect_set(F.col('id2')).over(Window.partitionBy('id1').orderBy('date').rangeBetween(-2678400, 0))) > 1).cast('int')
df = df.withColumn('flag', flag)
df = df.withColumn('date', F.col('date').cast('timestamp').cast('date'))
这个想法有点像

COUNT DISTINCT id2 OVER (PARTITION BY id1 ORDER BY date RANGE BETWEEN INTERVAL '1' MONTH PRECEDING AND CURRENT ROW)

对于行
|2010-07-10 | A | X | 0 |
,标志不应该是1,因为2020-05-10上有重复的条目吗?标志应该是0,因为对于
2
的窗口大小,当日期是
2010-07-10
时,我只想查看
2010-06-10
<代码>2010-05-10在这种情况下将被忽略。但您在最多两个月前的窗口内的任何日期内都说了
;)你是对的,我错了。现在在文本中修复了它!谢谢你的回答。我发现解决方案没有将
2010-06-10
标记为
a
的重复条目,即使它在
2010-05-10
中有重复映射。也许这是因为不是每个月都有30天。是的,那么也许我应该用31天来代替。我相信这仍然会引起问题,因为不是每个月都有31天。看来这个问题并不像我想象的那么简单,非常感谢你的帮助。啊,如果你只对此感兴趣的话,我应该提取月份并转换成整数!但接下来的一年会有一个问题,比如“2010-01”对“2009-12”