将ID映射到Hadoop/MapReduce中的矩阵行
我有用户购买产品的数据。我想创建一个大小为将ID映射到Hadoop/MapReduce中的矩阵行,hadoop,matrix,mapreduce,uniqueidentifier,unique-index,Hadoop,Matrix,Mapreduce,Uniqueidentifier,Unique Index,我有用户购买产品的数据。我想创建一个大小为| users |x| products |的二进制矩阵,这样矩阵中的元素(I,j)在user|I购买了product|j时为1,否则值为0 现在,我的数据看起来像 userA, productX userB, productY userA, productZ ... 1,1 2,2 1,3 userid和productid都是字符串。我的问题是,如何将这些ID映射到矩阵中的行索引(对于用户)和列索引(对于产品) 有超过一百万个独特的用户ID和大约三
| users |
x| products |
的二进制矩阵,这样矩阵中的元素(I,j)
在user|I
购买了product|j
时为1,否则值为0
现在,我的数据看起来像
userA, productX
userB, productY
userA, productZ
...
1,1
2,2
1,3
userid和productid都是字符串。我的问题是,如何将这些ID映射到矩阵中的行索引(对于用户)和列索引(对于产品)
有超过一百万个独特的用户ID和大约三百万个产品ID
为了更好地定义问题:给定上面类似的user1,product1
输入,如何将其转换为类似的内容
userA, productX
userB, productY
userA, productZ
...
1,1
2,2
1,3
其中,userA
映射到矩阵的第0行,userB
映射到第1行,productX
映射到第0列,依此类推
考虑到数据的大小,我不得不使用Hadoop Map Reduce,但无法想出一种简单有效的方法
如果我们能做到以下几点,就可以解决这个问题:
- 映射所有用户标识,并为所有映射任务发出相同的键(如“1”)
- 在减速器的
中,将setup()
计数器初始化为0long
- 在
中,将计数器值与输入的userId一起发出,并将计数器增加1reduce()
- 映射userId时,根据一个键发出每个userId,该键是从1,2,3…N中统一采样的整数(其中N是可配置的。例如,N=100)。在某种程度上,我们正在对输入集进行分区
- 在映射程序中,使用Hadoop计数器计算分配给每个随机分区的用户ID的数量
- 在reducer设置中,首先在映射阶段访问计数器,以确定为每个分区分配了多少ID。使用这些计数器确定该分区的
和start
值end
- 在
中迭代(计数)每个用户标识,并将矩阵rowId生成为reduce
+start\u分区
计数器
- write(用户Id、矩阵行Id)
我相信应该有一些我不知道的方法。我们可以使用散列/模来实现这一点吗?我们将如何处理比例冲突?
首先在映射阶段访问计数器
这将无法正常工作。我建议在本例中使用spark并使用zipWithIndex()
,它使整个任务基本上有3-4行代码。如果您对它的工作原理感到好奇的话。它并行地对所有分区进行计数,然后在下一阶段,它只使用每个分区的长度来生成每个分区的索引偏移量和每行的增量。这相当于有两个仅映射作业,其中通过configs或hdfs文件传输索引信息zipwithIndex
似乎是解决方案。然而,我不知道如何用1,1
替换userA,productX
。zipWithIndex
将如何替换产品ID?你有一些示例代码吗?你需要在产品名称本身上加入产品名称和zipWithIndex结果,这将在该列中为你提供索引。谢谢@ThomasJungblut。首先在映射阶段访问计数器
这不会奏效。我建议在本例中使用spark并使用zipWithIndex()
,它使整个任务基本上有3-4行代码。如果您对它的工作原理感到好奇的话。它并行地对所有分区进行计数,然后在下一阶段,它只使用每个分区的长度来生成每个分区的索引偏移量和每行的增量。这相当于有两个仅映射作业,其中通过configs或hdfs文件传输索引信息zipwithIndex
似乎是解决方案。然而,我不知道如何用1,1
替换userA,productX
。zipWithIndex
将如何替换产品ID?你有一些示例代码吗?你需要在产品名称本身上加入产品名称和zipWithIndex结果,这将在该列中为你提供索引。谢谢@ThomasJungblut。