如何在猪中生成行号?
Posted
技术标签:
【中文标题】如何在猪中生成行号?【英文标题】:How to generate a row number in pig? 【发布时间】:2012-03-01 02:26:12 【问题描述】:我正在使用 pig 进行数据准备,我遇到了一个看似简单但我无法处理的问题:
例如,我有一列名字
name
------
Alicia
Ana
Benita
Berta
Bertha
那么如何为每个名称添加行号?结果是这样的:
name | id
----------------
Alicia | 1
Ana | 2
Benita | 3
Berta | 4
Bertha | 5
感谢您阅读此问题!
【问题讨论】:
【参考方案1】:当您提出这个问题时,Pig 没有执行此操作的机制。但是,Pig 0.11 引入了可用于此目的的RANK operator。
【讨论】:
【参考方案2】:很遗憾,在 Pig Latin 中无法枚举行。至少,我找不到简单的方法。一种解决方案是使用执行实际枚举的单个 Reduce 任务来实现单独的 MapReduce 作业。更准确地说,
映射阶段:将所有行分配给相同的键。 单个 Reduce 任务:接收带有迭代器的单个键到所有行。由于reduce任务只在一台物理机器上运行,并且“reduce函数”只会被调用一次,函数内部的本地计数器解决了这个问题。
如果数据量很大且无法在单个reduce机器上处理,则可以使用master节点上的默认MapReduce Counters。
【讨论】:
谢谢你,Shatlyk,我也没有在 Pig Latin 中找到方法。是的,您只使用 1 个 reduce 节点的想法可以解决问题,尽管它不是真正的并行算法 由于reducer需要处理与整个mapper输入大小相同的数据,这将成为map-reduce程序的瓶颈。我认为很难实现像这样的真正并行程序,因为tasktrackers无法维护全局变量^^顺便说一句,最后我通过在单台机器上使用java程序解决了这个问题,速度很快:)【参考方案3】:草图想法,假设我们要排序的“名称”列是数字而不是字符串。 还假设良好的非偏态分布。
-
WITH_GROUPS = foreach TABLE 生成名称,名称 / 100 作为 group_id;
按 group_id 分组 WITH_GROUPS;
PER_GROUP = 生成组,计数(*);
ACCUM_PER_GROUP = 与自身交叉连接 PER_GROUP,计算每个组的累积计数;
按 group_id 将 ACCUM_PER_GROUP 与 WITH_GROUPS 共同分组;
在 reducer 中运行一个 UDF,为每一行分配一个从该组 accumulative_count 开始的 id
【讨论】:
【参考方案4】:@cabad
从表面上看,RANK 运算符确实可以工作,但如果不对数据提供一些限制,则不能保证您的行 ID 会不断增加。
问题来自于提供给排名运算符的任何行,如果它们是相同的,那么它们将共享相同的排名。如果你能保证没有两行有相同的字段用于排名,那么这种方法可能会奏效,但我想我会把它放在“方钉圆孔”方法中。
请参阅 [docs] http://pig.apache.org/docs/r0.11.0/basic.html#rank(排名 2、6、10)中的此示例:
C = rank A by f1 DESC, f2 ASC;
dump C;
(1,Tete,2,N)
(2,Ranjit,3,M)
(2,Ranjit,3,P)
(4,Michael,8,T)
(5,Jose,10,V)
(6,Jillian,8,Q)
(6,Jillian,8,Q)
(8,JaePak,7,Q)
(9,David,1,N)
(10,David,4,Q)
(10,David,4,Q)
【讨论】:
对于OP描述的用例,一个简单的RANK A;会工作的。以上是关于如何在猪中生成行号?的主要内容,如果未能解决你的问题,请参考以下文章