Apache pig 获取特定字符串的计数

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

我如何计算每一行特定字符串的发生次数,比如“Y”,然后再计算该次数。例如,我如何找到每个“FMID”的“Y”数并计算每个FMID的计数?

您可以使用令牌化内置函数将行转换为一个包,而不是在foreach中使用嵌套过滤来获得一个只包含您感兴趣的单词的包,您可以使用计数。看见 例如:

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");
}