Apache pig 获取特定字符串的计数
我如何计算每一行特定字符串的发生次数,比如“Y”,然后再计算该次数。例如,我如何找到每个“FMID”的“Y”数并计算每个FMID的计数?您可以使用令牌化内置函数将行转换为一个包,而不是在foreach中使用嵌套过滤来获得一个只包含您感兴趣的单词的包,您可以使用计数。看见 例如:Apache pig 获取特定字符串的计数,apache-pig,Apache Pig,我如何计算每一行特定字符串的发生次数,比如“Y”,然后再计算该次数。例如,我如何找到每个“FMID”的“Y”数并计算每个FMID的计数?您可以使用令牌化内置函数将行转换为一个包,而不是在foreach中使用嵌套过滤来获得一个只包含您感兴趣的单词的包,您可以使用计数。看见 例如: inpt = load '....' as (line : string); row_bags = foreach inpt generate line, TOKENIZE(line) as word; cnt = fo
inpt = load '....' as (line : string);
row_bags = foreach inpt generate line, TOKENIZE(line) as word;
cnt = foreach row_bags {
match_1 = filter word by 'Y';
match_2 = filter word by 'X';
generate line, COUNT(match_1) as count_1, COUNT(match_2) as count_2;
};
dump cnt;
使用DataFu库中的一些函数,您可以获得BAG word中每个字符串的计数。以下是解决问题的最简单方法:
define Transpose datafu.pig.util.TransposeTupleToBag();
data = LOAD 'input' USING PigStorage(',') AS
(fmid:int, field1:chararray, field2:chararray,
field3:chararray, field4:chararray);
data2 = FOREACH data GENERATE fmid, Transpose($1..) as fields;
data2 = FOREACH data2 {
y_fields = FILTER fields BY value == 'Y';
GENERATE fmid, SIZE(y_fields) as y_cnt;
}
我对您使用的数据模式不是很确定。我假设Pig中有一个关系,它由一系列元组组成。我还将假设您有很多字段,这使得单独引用每个字段非常困难
我将逐一介绍这个示例以进行解释。在不丧失一般性的情况下,我将使用以下数据作为示例:
data = LOAD 'input' USING PigStorage(',') AS (fmid:int, field1:chararray, field2:chararray, field3:chararray, field4:chararray);
现在我们已经加载了数据,我们希望将每个元组转置到一个包中,因为一旦它在一个包中,我们就可以更容易地对其中的项目进行计数。我们将使用库中的TransportSetupletoBag:
请注意,使用此UDF至少需要Pig 0.11。请注意$1..的使用,它在Pig中被称为项目范围表达式。如果你有很多领域,这真的很方便
如果此时要转储数据2,则会得到以下结果:
(1000,{(field1,N),(field2,N),(field3,N),(field4,N)})
(2000,{(field1,N),(field2,Y),(field3,N),(field4,N)})
(3000,{(field1,Y),(field2,Y),(field3,N),(field4,N)})
(4000,{(field1,Y),(field2,Y),(field3,Y),(field4,Y)})
我们所做的是从第0个元素(fmid)后面的元组中提取字段,并将这些字段转换成一个包,其中每个元组都有一个键和值字段
现在我们有了一个袋子,我们可以做一个简单的过滤和计数:
data2 = FOREACH data2 {
y_fields = FILTER fields BY value == 'Y';
GENERATE fmid, SIZE(y_fields) as y_cnt;
}
现在,如果转储数据2,则会得到反映元组中Y值数量的预期计数
(1000,0)
(2000,1)
(3000,2)
(4000,4)
以下是作为单元测试的示例的完整源代码,您可以直接将其放入DataFu单元测试中进行测试:
/**
register $JAR_PATH
define Transpose datafu.pig.util.TransposeTupleToBag();
data = LOAD 'input' USING PigStorage(',') AS (fmid:int, field1:chararray, field2:chararray, field3:chararray, field4:chararray);
data2 = FOREACH data GENERATE fmid, Transpose($1..) as fields;
dump data2;
data2 = FOREACH data2 {
y_fields = FILTER fields BY value == 'Y';
GENERATE fmid, SIZE(y_fields) as y_cnt;
}
dump data2;
STORE data2 INTO 'output';
*/
@Multiline
private String example;
@Test
public void example() throws Exception
{
PigTest test = createPigTestFromString(example);
writeLinesToFile("input",
"1000,N,N,N,N",
"2000,N,Y,N,N",
"3000,Y,Y,N,N",
"4000,Y,Y,Y,Y");
test.runScript();
super.getLinesForAlias(test, "data2");
}
我真的不知道如何使用pig,但可以建议一个SQL解决方案,也许这会给我一个想法。从表名中选择(SUM(IF(SFMNP=='Y',1,0))+SUM(IF(SNAP=='Y',1,0))+…+SUM(IF(Cheese=='Y',1,0)))这样做怎么样。这将为您提供每行中的
Y
数字,显示您尝试过的不起作用的代码。我想不出任何可以起作用的代码。我在网上也搜索了很多,但什么也没找到。FOREACH..GENERATE可以提供帮助,但不知道如何使用它添加“Y”的数量。我还尝试了UDF。下面是我的代码,它将以下内容作为输出。0 0 0 0 0 . . . 0 0我下载了Datafu(Datafu-1.0.0),当我在eclipse中打开它时,它抛出了很多错误(主要是导入错误)。请您澄清我应该在其中添加哪些库。另外,我使用的是Pig版本0.11.0-cdh4.4.0,datafu是针对Pig版本0.11.1以后的版本进行测试的。这可能是问题所在吗?您可能缺少eclipse的常春藤插件。检查插件安装说明。但是您也可以只从下载JAR目录,而不下载源代码。
/**
register $JAR_PATH
define Transpose datafu.pig.util.TransposeTupleToBag();
data = LOAD 'input' USING PigStorage(',') AS (fmid:int, field1:chararray, field2:chararray, field3:chararray, field4:chararray);
data2 = FOREACH data GENERATE fmid, Transpose($1..) as fields;
dump data2;
data2 = FOREACH data2 {
y_fields = FILTER fields BY value == 'Y';
GENERATE fmid, SIZE(y_fields) as y_cnt;
}
dump data2;
STORE data2 INTO 'output';
*/
@Multiline
private String example;
@Test
public void example() throws Exception
{
PigTest test = createPigTestFromString(example);
writeLinesToFile("input",
"1000,N,N,N,N",
"2000,N,Y,N,N",
"3000,Y,Y,N,N",
"4000,Y,Y,Y,Y");
test.runScript();
super.getLinesForAlias(test, "data2");
}