我有一个表格,其中包含由uid分组的事件。所有行都包含uid
,visit_num
和event_num
列。
visit_num
是一个偶尔增加的任意计数器。 event_num
是访问中互动的反击。
我想将这两个计数器合并到一个交互计数器中,该计数器对每个事件保持增加1,并在下次访问开始时继续增加。
由于我只看事件之间的相对距离,如果我不在1开始计数器,那就没问题。
|uid |visit_num|event_num|interaction_num|
| 1 | 1 | 1 | 1 |
| 1 | 1 | 2 | 2 |
| 1 | 2 | 1 | 3 |
| 1 | 2 | 2 | 4 |
| 2 | 1 | 1 | 500 |
| 2 | 2 | 1 | 501 |
| 2 | 2 | 2 | 502 |
我可以通过重新分区数据并使用monotonically_increasing_id
这样来实现这一点:
df.repartition("uid")\
.sort("visit_num", "event_num")\
.withColumn("iid", fn.monotonically_increasing_id())
然而,文件说明:
生成的ID保证单调增加且唯一,但不是连续的。当前实现将分区ID放在高31位中,将每个分区中的记录号放在低33位中。假设数据框的分区少于10亿,每个分区的记录少于80亿。
由于id似乎通过分区单调增加,这似乎很好。但是:
有没有办法可以用1作为第一个交互数量来启动每个uid?
修改
经过测试后,我注意到有些用户似乎没有使用上述方法连续iid
值。
编辑2:窗口
不幸的是,有一些(罕见)情况超过one row has the same
visit_num and
event_num`。我已尝试使用如下窗口函数,但由于这会将相同的排名分配给两个相同的列,因此这不是一个真正的选项。
iid_window = Window.partitionBy("uid").orderBy("visit_num", "event_num")
df_sample_iid=df_sample.withColumn("iid", fn.rank().over(iid_window))
答案 0 :(得分:0)
最好的解决方案是具有等级的窗口函数,如Jacek Laskowski所建议的那样。
iid_window = Window.partitionBy("uid").orderBy("visit_num", "event_num")
df_sample_iid=df_sample.withColumn("iid", fn.rank().over(iid_window))
在我的具体情况下,需要更多数据清理,但一般来说,这应该有效。