2016-04-07 29 views
0

我對Pig/Python相當陌生,需要幫助。試圖編寫一個協調財務數據的豬腳本。使用的參數遵循像(grand_tot,x1,x2,... xn)這樣的語法,這意味着第一個值應該等於剩餘值的總和。Python:總結一個包含浮點值的豬元組

我不知道使用Pig單獨完成此操作的方法,所以我一直在嘗試編寫一個Python UDF。豬把元組傳遞給Python;如果x1:xn的總和等於grand_tot,那麼Python應該向Pig返回「1」以表明數字匹配,否則返回「0」。

這是我到目前爲止有:

register 'myudf.py' using jython as myfuncs; 
A = LOAD '$file_nm' USING PigStorage(',') AS (grand_tot,west_region,east_region,prod_line_a,prod_line_b, prod_line_c, prod_line_d); 
A1 = GROUP A ALL; 
B = FOREACH A1 GENERATE TOTUPLE($recon1) as flds; 
C = FOREACH B GENERATE myfuncs.isReconciled(flds) AS res; 
DUMP C; 

$ RECON1被作爲參數傳遞,並定義爲:

grand_tot, west_region, east_region 

稍後我會通過$ RECON2爲:

grand_tot, prod_line_a, prod_line_b, prod_line_c, prod_line_d 

樣品行數據(在$ file_nm)看起來像:

grand_tot,west_region,east_region,prod_line_a,prod_line_b, prod_line_c, prod_line_d 
10000,4500,5500,900,2200,450,3700,2750 
12500,7500,5000,3180,2770,300,3950,2300 
9900,7425,2475,1320,460,3070,4630,1740 

最後...這裏是我想要使用Python UDF代碼做:

@outputSchema("result") 
def isReconciled(arrTuple): 
    arrTemp = [] 
    arrNew = [] 
    string1 = "" 
    result = 0 
    ## the first element of the Tuple should be the sum of remaining values 
    varGrandTot = arrTuple[0] 
    ## create a new array with the remaining Tuple values 
    arrTemp = arrTuple[1:] 

    for item in arrTuple: 
     arrNew.append(item) 

    ## sum the second to the nth values 
    varSum = sum(arrNew) 

    ## if the first value in the tuple equals the sum of all remaining values 
    if varGrandTot = varSum then: 
     #reconciled to the penny 
     result = 1 
    else: 
     result = 0 

    return result 

我收到錯誤消息:爲+ 不支持的操作數類型(S):「詮釋」和「array.array」

我試過很多東西試圖數組值轉換爲數字,並轉換爲浮動等等我可以總結,但沒有成功。

任何想法???感謝您的期待!

回答

1

您可以在PIG本身中執行此操作。

首先,在模式中指定數據類型。 PigStorage將使用bytearray作爲默認的數據類型。所以你的python腳本拋出錯誤。看起來你的樣本數據是int,但是在你提到的問題中浮點數。

其次,添加從第二個字段或您選擇的字段開始的字段。

第三,使用二進制運算符來檢查第一個字段值與總和。

A = LOAD '$file_nm' USING PigStorage(',') AS (grand_tot:float,west_region:float,east_region:float,prod_line_a:float,prod_line_b:float, prod_line_c:float, prod_line_d:float); 
A1 = FOREACH A GENERATE grand_tot,SUM(TOBAG(prod_line_a,prod_line_b,prod_line_c,prod_line_d)) as SUM_ALL; 
B = FOREACH A1 GENERATE (grand_tot == SUM_ALL ? 1 : 0); 
DUMP B; 
+0

這個工程,有一些調整。沒有Python,性能也有所提高(獎金)。謝謝。 – JaneQDoe

+0

@JaneQDoe Cool.Please標記它的答案,如果它回答你的問題 –

0

很有可能,您的arrTuple不是數組的數組,但某些項是數組。

要檢查它,通過添加一些檢查,修改代碼:

@outputSchema("result") 
def isReconciled(arrTuple): 
    # some checks 
    tmpl = "Item # {i} shall be a number (has value {itm} of type {tp})" 
    for i, num in enumerate(arrTuple): 
     msg = templ.format(i=i, itm=itm, tp=type(itm)) 
     assert isinstance(arrTuple[0], (int, long, float)), msg 
    # end of checks 

    arrTemp = [] 
    arrNew = [] 
    string1 = "" 
    result = 0 
    ## the first element of the Tuple should be the sum of remaining values 
    varGrandTot = arrTuple[0] 
    ## create a new array with the remaining Tuple values 
    arrTemp = arrTuple[1:] 

    for item in arrTuple: 
     arrNew.append(item) 

    ## sum the second to the nth values 
    varSum = sum(arrNew) 

    ## if the first value in the tuple equals the sum of all remaining values 
    if varGrandTot = varSum then: 
     #reconciled to the penny 
     result = 1 
    else: 
     result = 0 

    return result 

這是非常有可能的,它會扔在一個項目的AssertionFailed例外。閱讀 斷言信息以瞭解哪個項目正在製造麻煩。

無論如何,如果你想,如果第一數目等於該陣列的其餘部分的總和返回0或1,以下 將工作太:

@outputSchema("result") 
def isReconciled(arrTuple): 
    if arrTuple[0] == sum(arrTuple[1:]): 
     return 1 
    else: 
     return 0 

,並在情況下,你會活的快樂與得到True而不是1和False而不是0:

@outputSchema("result") 
def isReconciled(arrTuple): 
    return arrTuple[0] == sum(arrTuple[1:])