2017-05-19 42 views
0

我有一個表格,其中包含由uid分組的事件。所有行都有列uid,visit_numevent_numSpark:根據兩列計數事件

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()) 

但是文件指出:

的根erated ID保證單調遞增並且是唯一的,但不是連續的。當前實現將分區ID放在高31位中,並將每個分區中的記錄號放在低33位中。假設數據幀的分區少於10億個,每個分區的記錄少於80億個。

由於ID似乎是通過分區單調增加,這似乎很好。但是:

  • 我接近達到10億分區/ uid閾值。
  • 我不想依靠目前的實現沒有改變。

有沒有一種方法,我可以啓動每個用1作爲第一個交互數字的數字?

編輯

經過測試該多一些,我注意到,有些用戶似乎並不具備使用上述方法連續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))  
+1

您是否考慮過使用窗口集合函數,如rank?這可以在分區內工作,然後您必須在整個數據集上應用「滯後」或相似性。這可以工作(不知道它是如何有效的表現明智)。 –

+0

我已經測試了級別的窗口,它完成了問題中最初概述的工作。不幸的是,我發現它造成了重複行的一些問題,我不希望在數據中看到這些問題。 – Hans

+1

'row_number'呢?你檢查過了嗎? –

回答

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)) 

在我的具體情況下,需要更多的數據清理,但通常這應該起作用。