将多个参数传递给 Pig Filter UDF

Posted

技术标签:

【中文标题】将多个参数传递给 Pig Filter UDF【英文标题】:Pass mutiple parameters to Pig Filter UDF 【发布时间】:2015-12-06 07:09:33 【问题描述】:

我是 Pig 脚本的新手。

我想将多个参数传递给 Pig 过滤器 UDF,但出现错误“标量投影无效:需要从关系中投影一列才能用作标量”

我正在执行以下步骤。

    input = load '....';
    dump input; /* working able to see data*/
    output = FILTER input by not FilterUDF(input,val1,val2);

这没有奏效。所以我尝试了以下。

    input = load '......';
    dump input; /* working able to see data*/
    dataWithVal = FOREACH input GENERATE $0,$1,val1,val2;
    dump dataWithVal; /* working able to see data with values*/
    output = FILTER dataWithVal by not FilterUDF(dataWithVal);

这也没有用。所以我将我的值添加到一个文件中,将该文件复制到 HDFS 中,然后将其与输入数据交叉连接,但仍然出现相同的错误。

    input = load '........';
    dump input; /* working able to see data*/
    val = load '........';
    dump val; /* working able to values*/
    interData = cross input, val;
    dump interData; /* working able to see cross joined data*/
    output = FILTER interData by not FilterUDF(interData);

对于上述所有选项,我得到的错误与“无效的标量投影:需要从关系中投影一列才能用作标量。”

对于第一种情况,我的FilterUDF结构如下。

    import org.apache.pig.FilterFunc;
    import java.io.IOException;
    import org.apache.pig.data.Tuple;


    public class FilterUDF extends FilterFunc 
        public boolean exec(Tuple input, int val, String Val) throws IOException 
         /*some code here*/
        
    

尝试了一种替代方法但没有奏效。

    import org.apache.pig.FilterFunc;
    import java.io.IOException;
    import org.apache.pig.data.Tuple;

    public class FilterUDF extends FilterFunc 

        private Tuple input;
        private int Ival;
        private String Sval;

        public FilterUDF(Tuple input, int Ival, String Sval)
            this.input = input;
            this.Ival = Ival;
            this.Sval = Sval;
        

        public Boolean exec(Tuple arg0) throws IOException 
        /*Some code*/   
        
    

对于情况二和三,我的FilterUDF结构如下。

    import org.apache.pig.FilterFunc;
    import java.io.IOException;
    import org.apache.pig.data.Tuple;


    public class FilterUDF extends FilterFunc 

        public Boolean exec(Tuple input) throws IOException 
        /*some code here*/
        
    

我做错了什么? 如何将多个参数传递给 Pig UDF? “无效标量投影”错误背后的原因是什么?

在此先感谢您的帮助。

【问题讨论】:

【参考方案1】:

我不确定您要使用 UDF 计算什么,因为您的问题描述有点模糊,但在您的所有三个代码示例中,您都试图将关系传递给您的 UDF,而这并没有真正有意义(输入、dataWithVal 和 interData 是关系)。您需要传递它。因此,假设您使用 UDF 断言 val1 和 val2 相同(或其他),那么您可以编写

input = LOAD '...';  /* load some data */
output = FILTER input BY FilterUDF(val1, val2);

你的 UDF 看起来像

import org.apache.pig.FilterFunc;
import java.io.IOException;
import org.apache.pig.data.Tuple;


public class FilterUDF extends FilterFunc 
    public Boolean exec(Tuple input) throws IOException 
        if (input == null || input.size() == 0)
            return null;

        int val1 = input.get(0)  // gets val1 from pig
        int val2 = input.get(1)  // gets val2 from pig

    /*rest of code*/
    

如您所见,您可以向 UDF 传递任意数量的参数;这就是org.apache.pig.data.Tuple 的用途;只需根据需要传递尽可能多的参数,然后在 UDF 中使用 .get(i) 解析它们

【讨论】:

非常感谢 GoBrewers14 的回复。我想要实现的是,我想根据关系中的一些值过滤数据。例如,我只想要工资低于 10000 的部门 10 的员工。emp = load '/emp.csv' using PigStorage(',') as (name,dept); filteremp = FILTER emp by FilterUDF(emp,10,1000); 和在 UDF 中,我计划使用 get(1) 从 emp 关系中提取部门,然后应用我的逻辑。可能还有其他方法可以实现这一目标,但我想遵循这个。 1)。您正在使这种 方式 比使用 UDF 更复杂。 2)。当没有名为salary 的列时,如何过滤salary 抱歉,加载数据时忘记添加薪水栏。 emp = load '/emp.csv' using PigStorage(',') as (name,dept,salary); filteremp = FILTER emp by FilterUDF(emp,10,1000); 然后 get(1) 代表部门,get(2) 代表工资。它会起作用吗?我究竟做错了什么?我也想按照同样的方式,那我要对现有代码做哪些改动呢?

以上是关于将多个参数传递给 Pig Filter UDF的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 Pig 脚本中将参数传递给 UDF 吗?

如何将 UDF 的输入参数传递给 sapply

如何在 PySpark 中将多个参数传递给 Pandas UDF?

Pyspark 将函数作为参数传递给 UDF

将列表作为参数传递给 udf 方法

通过python UDF将文本文件导入pig