我有一个数据框,该数据框提供一组ID号以及他们访问特定位置的日期,我正在尝试在Spark Scala中找到一种方法来获取具有以下ID的唯一身份人员(“ ID”)的数量:每天或之前访问此位置,例如,如果一个ID号在2019-01-01到2019-01-07再次访问,则不会被计算两次。
df.show(5,false)
+---------------+
|id |date |
+---------------+
|3424|2019-01-02|
|8683|2019-01-01|
|7690|2019-01-02|
|3424|2019-01-07|
|9002|2019-01-02|
+---------------+
我希望输出看起来像这样:在哪里我groupBy(“ date”)并获得唯一ID的计数作为累积数字。 (因此,例如:在2019年1月3日旁边,它将提供截至2019年1月3日的任意一天的ID的唯一计数)
+----------+-------+
|date |cum_ct |
+----------+-------+
|2019-01-01|xxxxx |
|2019-01-02|xxxxx |
|2019-01-03|xxxxx |
|... |... |
|2019-01-08|xxxxx |
|2019-01-09|xxxxx |
+------------------+
在df.groupBy(“ date”)之后执行此操作的最佳方法是什么?
答案 0 :(得分:0)
在这种情况下,您将必须使用ROW_NUMBER()函数。我已经创建了一个数据框
val df = Seq((1,"2019-05-03"),(1,"2018-05-03"),(2,"2019-05-03"),(2,"2018-05-03"),(3,"2019-05-03"),(3,"2018-05-03")).toDF("id","date")
df.show
+---+----------+
| id| date|
+---+----------+
| 1|2019-05-03|
| 1|2018-05-03|
| 2|2019-05-03|
| 2|2018-05-03|
| 3|2019-05-03|
| 3|2018-05-03|
+---+----------+
ID代表您的情况下的人员ID,可以针对多个日期显示。
这是每个日期的计数。
df.groupBy("date").count.show
+----------+-----+
| date|count|
+----------+-----+
|2018-05-03| 3|
|2019-05-03| 3|
+----------+-----+
这显示了每个日期对ID的重复计数。我总共使用了3个id,每个日期都有3个计数,这意味着所有id在每个日期中都被明确计数。
据我所知,您希望对任何日期仅对ID进行一次计数(取决于您是希望最新日期还是最早的日期)。
我将为每个ID使用最新日期。
val newdf = df.withColumn("row_num",row_number().over(Window.partitionBy($"id").orderBy($"date".desc)))
以上一行将针对每个ID为其输入的每个日期分配行号,并且行号1表示每个ID的最新日期,现在您对行号为1的每个ID进行计数。每个ID的唯一计数(不重复)。
这里是输出,我对行号应用了过滤器,您可以在输出中看到日期是最新的,即我的情况是2019年。
newdf.select("id","date","row_num").where("row_num = 1").show()
+---+----------+-------+
| id| date|row_num|
+---+----------+-------+
| 1|2019-05-03| 1|
| 3|2019-05-03| 1|
| 2|2019-05-03| 1|
+---+----------+-------+
现在,我将使用具有相同过滤器的NEWDF进行计数,该过滤器将返回按日期进行计数。
newdf.groupBy("date","row_num").count().filter("row_num = 1").select("date","count").show
+----------+-----+
| date|count|
+----------+-----+
|2019-05-03| 3|
+----------+-----+
这里的总数为3,其中不包括先前日期的ID,之前为6(因为ID在多个日期重复)
希望它能回答您的问题。