如何在猪中生成行号?

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;会工作的。

以上是关于如何在猪中生成行号?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MySQL,如何在表中生成包含记录索引的列?

如何在猪中加载由 :: 分隔的数据

如何在猪中读取json数据?

如何在猪中使用 rcfilepigstorage

如何在猪的时间序列中计算

如何在访问报告中生成列表?