2016-04-07 5 views
0

Ich bin ziemlich neu zu Pig/Python und brauche Hilfe. Versuch, ein Schweineskript zu schreiben, das Finanzdaten abgleicht. Die verwendeten Parameter folgen einer Syntax wie (grand_tot, x1, x2, ... xn), was bedeutet, dass der erste Wert der Summe der verbleibenden Werte entsprechen sollte.Python: Summiere ein Schwein Tupel mit Float-Werten

Ich kenne keine Möglichkeit, dies mit Pig allein zu erreichen, also habe ich versucht, eine Python UDF zu schreiben. Pig übergibt ein Tupel an Python; Wenn die Summe von x1: xn gleich grand_tot ist, sollte Python eine "1" an Pig zurückgeben, um zu zeigen, dass die Zahlen übereinstimmen, andernfalls wird eine "0" zurückgegeben. Hier

ist das, was ich bisher:

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 $ wird als Parameter übergeben, und wie folgt definiert:

grand_tot, west_region, east_region 

ich später $ recon2 passieren wird als:

grand_tot, prod_line_a, prod_line_b, prod_line_c, prod_line_d 

Probenreihe von Daten (in $ file_nm) wie folgt aussehen:

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 

Schließlich ... hier ist das, was ich versuche, mit Python UDF-Code zu tun:

@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 

Die Fehlermeldung erhalte ich ist : nicht unterstützter Operandtyp (e) für +: ‚int‘ und ‚array.array‘

ich habe versucht, zahlreiche Dinge versucht, die Array-Werte in numerischen zu konvertieren und konvertieren, so zu schweben das kann ich summieren, aber ohne Erfolg.

Irgendwelche Ideen ??? Danke fürs schauen!

Antwort

1

Sie können dies selbst in PIG tun.

Geben Sie zuerst den Datentyp im Schema an. PigStorage verwendet Bytearray als Standarddatentyp. Daher wirft Ihr Python-Skript den Fehler.Sieht so aus, als hätten Ihre Beispieldaten int, aber in Ihrer Frage, die Sie erwähnt haben, float.

Zweitens, fügen Sie die Felder beginnend mit dem zweiten Feld oder den Feldern Ihrer Wahl hinzu.

Drittens, verwenden Sie den bincond-Operator, um den ersten Feldwert mit der Summe zu überprüfen.

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

Dies funktioniert, mit ein paar Verbesserungen. Die Leistung hat sich auch ohne Python verbessert (ein Bonus). Vielen Dank. – JaneQDoe

+0

@JaneQDoe Cool.Please markieren Sie die Antwort, wenn es Ihre Frage beantwortet –

0

Es ist sehr wahrscheinlich, dass Ihr arrTuple kein Array von Zahlen ist, aber ein Element ein Array ist.

es zu überprüfen, ändern Sie den Code durch einige Prüfungen ergänzt:

@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 

Es ist sehr wahrscheinlich, dass es eine AssertionFailed Ausnahme auf eines der Elemente werfen. Lesen Sie die Bestätigungsmeldung , um zu erfahren, welches Element die Probleme verursacht.

Wie auch immer, wenn Sie 0 oder 1 zurückkehren wollen, wenn erste Zahl Summe des Restes des Arrays entspricht, folgende würde auch funktionieren:

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

und im Fall würden Sie mit dem Erhalten True glücklich leben anstelle von 1 und False statt 0:

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