PIG-使用python UDF(窗口函数)按组计算记录之间的差异

PIG-使用python UDF(窗口函数)按组计算记录之间的差异,python,apache-pig,window-functions,udf,enumerate,Python,Apache Pig,Window Functions,Udf,Enumerate,我试图按组计算记录之间的差异,并按组包括行数。这可以通过使用窗口函数在配置单元中使用滞后和行号函数来实现。正在尝试使用PIG和python UDF重新创建它 在下面的示例中,我需要为每个名称从1重新启动行号,并为新的月份(新记录)增加行号。另外,我需要每个名字的余额与上个月的差额 输入数据 输出数据 如何使用PIG和python UDF实现这一点?下面是我试过的 猪 Python自定义项 我的python函数可以工作。然而,一旦我把结果带到PIG中,我就很难将这两个包(分类和行详细信息)组合起来

我试图按组计算记录之间的差异,并按组包括行数。这可以通过使用窗口函数在配置单元中使用滞后和行号函数来实现。正在尝试使用PIG和python UDF重新创建它

在下面的示例中,我需要为每个名称从1重新启动行号,并为新的月份(新记录)增加行号。另外,我需要每个名字的余额与上个月的差额

输入数据

输出数据

如何使用PIG和python UDF实现这一点?下面是我试过的

Python自定义项

我的python函数可以工作。然而,一旦我把结果带到PIG中,我就很难将这两个包(分类和行详细信息)组合起来。非常感谢您的帮助

我还看到PIG中的枚举函数对行号执行我想要的操作。然而,作为学习PIG的一部分,我正在寻找使用python UDF的解决方案。

试试这个

Python UDF:

def row_num(mth):
    return [x+1 for x,y in enumerate (mth)]

def diff(bal, n=1):
    return [0]+[x-y for x,y in zip(bal[n:],bal[:-n])]


@outputSchema('udfbag:bag{udftuple:tuple(name: chararray, mth: int, row_number: int, balance_diff: int)}')

def row_metrics(mthbal):
    name, mth, bal = zip(*mthbal)
    row_number = row_num(mth)
    balance_diff = diff(bal)
    return zip(name,mth,row_number, balance_diff)
猪字:

register 'myudf.py' using jython as myudf;
inpdat = load 'input.dat' using PigStorage(',') as (name:chararray, month:int, balance:int);

outdat = foreach (group inpdat by name) {
    sorted = order inpdat BY month asc;
    row_details = myudf.row_metrics(sorted);
    generate flatten (row_details);
    };

dump outdat;

在我的案例中,使用piggybank的stitch函数是有效的。我有兴趣学习任何其他方法来做到这一点

REGISTER /mypath/piggybank.jar;
define Stitch org.apache.pig.piggybank.evaluation.Stitch;

input = load 'input.dat' using PigStorage(',') as (name:chararray, month:int, balance:int);

output = FOREACH (group input by name) { 
sorted = ORDER input by month asc; 
udf_fields = myudf.row_metrics(sorted.(month, balance));
generate flatten(Stitch(sorted,udf_fields)) as (name, month, balance, row_number, balance_diff);
};

这段代码中似乎有bug。python代码中的
[:n]
中有一个错误,
rownum_和_diff
应该是
row_metrics
Hi@Dhanseh,感谢您在myudf上捕获错误。行_num_和_diff——忘记重命名它了。我的diff函数的原始代码运行良好。我试图使用相同的函数,即使我必须计算两个月或三个月前的余额差额。我的原始函数返回相同的数字元素,而不考虑n的值(这是我想要的)。但是,我注意到,当n>1时,代码返回的元素较少。再次感谢您的帮助。感谢您发布解决方案。虽然这样做有效,但我试图避免这种解决方案。原因是,我的实际关系有很多领域。当您仅使用2个字段进行计算,而使用python UDF创建更多的计算字段时,将整个字段发送到python并将它们全部返回到pig和一些其他计算字段是没有意义的。我终于找到了解决这个问题的方法(贴在下面),但是,因为我是一个猪的初学者,我很想知道是否还有其他方法可以解决这个问题。
def row_num(mth):
    return [x+1 for x,y in enumerate (mth)]

def diff(bal, n=1):
    return [x-y if (x is not None and y is not None) else 0.0 \
        for x,y in zip(bal, [:n] + bal)]

@outputSchema('udfbag:bag{udftuple:tuple(row_number: int, balance_diff: int)}')

def row_metrics(mthbal):
    mth, bal = zip(*mthbal)
    row_number = row_num(mth)
    balance_diff = diff(bal)
    return zip(row_number, balance_diff)
def row_num(mth):
    return [x+1 for x,y in enumerate (mth)]

def diff(bal, n=1):
    return [0]+[x-y for x,y in zip(bal[n:],bal[:-n])]


@outputSchema('udfbag:bag{udftuple:tuple(name: chararray, mth: int, row_number: int, balance_diff: int)}')

def row_metrics(mthbal):
    name, mth, bal = zip(*mthbal)
    row_number = row_num(mth)
    balance_diff = diff(bal)
    return zip(name,mth,row_number, balance_diff)
register 'myudf.py' using jython as myudf;
inpdat = load 'input.dat' using PigStorage(',') as (name:chararray, month:int, balance:int);

outdat = foreach (group inpdat by name) {
    sorted = order inpdat BY month asc;
    row_details = myudf.row_metrics(sorted);
    generate flatten (row_details);
    };

dump outdat;
REGISTER /mypath/piggybank.jar;
define Stitch org.apache.pig.piggybank.evaluation.Stitch;

input = load 'input.dat' using PigStorage(',') as (name:chararray, month:int, balance:int);

output = FOREACH (group input by name) { 
sorted = ORDER input by month asc; 
udf_fields = myudf.row_metrics(sorted.(month, balance));
generate flatten(Stitch(sorted,udf_fields)) as (name, month, balance, row_number, balance_diff);
};