使用Spark进行RDD和元组操作

时间:2018-08-09 09:45:43

标签: apache-spark pyspark apache-spark-sql

我刚刚开始使用Spark,但遇到的问题是我真的不知道该如何处理。

我的输入是以下格式的RDD:

[(u'7362', (u'2016-06-29 09:58:35', 0)), (u'8600', (u'2016-06-29 20:47:27', 1)), (u'f9f8', (u'2016-07-01 00:48:55', 2)), (u'c6c9', (u'2016-07-04 20:29:19', 3)), (u'218b', (u'2016-07-05 20:54:45', 4))]

所以结构是

[(user_id, (time_stamp, index))]

我需要做的是返回列表列表或元组列表。

如果我们以表格式查看RDD,这会更容易。用更“经典”的表格形式说出上述rdd。

[(u'7362', (u'2016-06-29 09:58:35', 0)), 
(u'8600', (u'2016-06-29 20:47:27', 1)), 
(u'7362', (u'2016-07-01 00:48:55', 2)), 
(u'c6c9', (u'2016-07-04 20:29:19', 3)), 
(u'8600', (u'2016-07-05 20:54:45', 4))]

我需要首先按用户将此RDD分组,所以最终我将获得三个RDD(每个用户一个,非重复用户一个)。

[(u'7362', (u'2016-06-29 09:58:35', 0)), 
(u'7362', (u'2016-07-01 00:48:55', 2))]

[(u'8600', (u'2016-06-29 20:47:27', 1)), 
(u'8600', (u'2016-07-05 20:54:45', 4))]

[(u'c6c9', (u'2016-07-04 20:29:19', 3))]

现在,对于仅包含一个user_id(前两个)的“表”,我需要计算与上一行的每一行的时间差,以及与每个先前索引的每个索引的时差(考虑到这些“表”有很多多于2行)。 这将给出类似表:

[(u'7362', (35, 2)), (u'7362', (21, 1)), (u'7362', (12, 3)), (u'7362', (41, 2)), (u'7362', (46, 2)), (u'7362', (31, 1)), (u'7362', (97, 3)) ...]

对于第一个user_id

[(u'8600', (78, 2)), (u'8600', (43, 1)), (u'8600', (99, 3)), (u'8600', (3, 2)), (u'8600', (15, 2)), (u'8600', (42, 1)), (u'8600', (11, 3)) ...]

,依此类推,对于所有用户,对于所有行,格式为[(user_idx, (dt=t2-t1, didx=idx2-idx1))]dtdidx是通过从当前行值中减去先前的行值而得出的。

最后,当我拥有以上所有表时,对于每个用户,我想将它们分组为一个嵌套列表,如下所示:

[[1, [21, 31, 43, 42]], [2, [35, 41, 46, 78, 3, 15]], [3, [12, 97, 99, 11]]]

所以最终的格式是[[didx, [dt1, dt2 ...]],在这里我不再关心user_ids了,只是所有用户的索引以及与同一索引相关的每次时间差。

我试图尽力清楚地解释问题,但是,就像我说的那样,我真的刚刚开始使用Spark,我知道这里没有真正的表格。

1 个答案:

答案 0 :(得分:1)

当您通过userId分组时,这不会导致多个RDD,而是一个RDD [(UserId,list [(time,index)]]形式的RDD。因此,在这种情况下,我将执行groupBy,然后将用户列表处理为格式,然后按照您所说的对didx进行分组,最后从RDD中收集结果以列出。

# assume each user has more than one event 
# if this ^ assumption is incorrect, you could filter the RDD before processing to get rid of users 
# with only one event
# also, assume timesteps can be subtracted (there are libraries for this)
def process(indexedTimes):
    num_times = len(indexedTimes)
    new_list = []
    for i in range(1,num_times):
        new_list.append((indexedTimes[i][1]-indexedTimes[i-1][1],datediff(indexedTimes[i][0]-indexedTimes[i-1][0])))
    return new_list

data                                                     # RDD[(userId, (timestep, index))]
  .groupByKey                                            # now RDD[(userId, list[(timestep, index)])]
  .flatMap(lambda userList: process(list(userList[1])))  # now RDD[(didx, dt)]
  .groupByKey                                            # now RDD[(didx, list(dt))]
  .collect                                               # get elements in final list instead of RDD