2013-08-31 12 views
8

Da questo:Come appiattire un gruppo in una singola tupla nel maiale?

(1, {(1,2), (1,3), (1,4)}) 
(2, {(2,5), (2,6), (2,7)}) 

... Come potremmo generare questo?

((1,2),(1,3),(1,4)) 
((2,5),(2,6),(2,7)) 

... E come possiamo generare questo?

(1, 2, 3, 4) 
(2, 5, 6, 7) 

Per una singola riga so come fare. Il problema è quando devo ripetere su molte righe E manipolare i gruppi interni allo stesso tempo.

risposta

11

Per la vostra domanda, ho preparato il seguente file:

1,2 
1,3 
1,4 
2,5 
2,6 
2,7 

In un primo momento, ho usato il seguente script per ottenere l'ingresso r3 che lei ha descritto nella sua domanda:

r1 = load 'test_file' using PigStorage(',') as (a:int, b:int); 
r2 = group r1 by a; 
r3 = foreach r2 generate group as a, r1 as b; 
describe r3; 
-- r3: {a: int,b: {(a: int,b: int)}} 
-- r3 is like (1, {(1,2), (1,3), (1,4)}) 

Se noi voglio generare il seguente contenuto,

(1, 2, 3, 4) 
(2, 5, 6, 7) 

possiamo usare il fol sceneggiatura muggito:

r4 = foreach r3 generate a, FLATTEN(BagToTuple(b.b)); 
dump r4; 

Per i seguenti contenuti,

((1,2),(1,3),(1,4)) 
((2,5),(2,6),(2,7)) 

non riesco a trovare alcuna funzione built-in utile. Forse hai bisogno di scrivere il tuo BagToTuple personalizzato. Ecco i codici sorgente BagToTuple incorporati: http://www.grepcode.com/file/repo1.maven.org/maven2/org.apache.pig/pig/0.11.1/org/apache/pig/builtin/BagToTuple.java#BagToTuple.getOuputTupleSize%28org.apache.pig.data.DataBag%29

+0

E se ci sono più di un campo, 1,2,3 1,3 , 4 1,4,5 2,5,6 2,6,7 2,7,7 e vogliamo l'uscita come (1, 2,3,3,4,4,5) (2, 5,6, 6,7, 7,8) – pratiklodha

3

Non esiste un modo incorporato per convertire una borsa in una tupla. Questo perché le buste sono non ordinate set di tuple, quindi Pig non sa in che ordine devono essere impostate le tuple quando viene convertito in una tupla. Ciò significa che dovrai scrivere una UDF per fare ciò.

Non sono sicuro di come si crea la tupla (1, 2, 3, 4), ma questo è un altro buon candidato per un UDF, anche se è possibile creare quello schema con solo l'UDF BagToTuple.

NOTA: Probabilmente non si dovrebbe trasformare nulla in una tupla se non si sa esattamente quanti campi ci sono.

myudfs.py

#!/usr/bin/python 

@outputSchema('T:(T1:(a1:chararray, a2:chararray), T2:(b1:chararray, b2:chararray), T3:(c1:chararray, c2:chararray))') 
def BagToTuple(B): 
    return tuple(B) 

def generateContent(B): 
    foo = [B[0][0]] + [ t[1] for t in B ] 
    return tuple(foo) 

myscript.maiale

REGISTER 'myudfs.py' USING jython AS myudfs ; 

-- A is (1, {(1,2), (1,3), (1,4)}) 
-- The schema is (I:int, B:{T:(I1:int, I2:int)}) 

B = FOREACH A GENERATE myudfs.BagToTuple(B) ; 
C = FOREACH A GENERATE myudfs.generateContent(B) ; 
4

Al fine di ottenere:

((1,2),(1,3),(1,4)) 
((2,5),(2,6),(2,7)) 

Si può fare questo:

r4 = foreach r3 { 
    Tmp=foreach $1 generate (a,b); 
    generate FLATTEN(BagToTuple(Tmp)); 
}; 
+0

Soluzione incredibile! perché non r4 = foreach r3 genera BagToTuple (b) funziona? Mi dà ((1,4,1,3,1,2)) ((2,7,2,6,2,5)), che sembra irrazionale. –