2011-02-08 11 views
7

Digamos que tengo un conjunto de datos de reseñas de restaurantes:¿Puedo generar bolsas anidadas usando declaraciones anidadas de FOREACH en Pig Latin?

User,City,Restaurant,Rating 
Jim,New York,Mecurials,3 
Jim,New York,Whapme,4.5 
Jim,London,Pint Size,2 
Lisa,London,Pint Size,4 
Lisa,London,Rabbit Whole,3.5 

Y quiero producir una lista por el usuario y la ciudad de revisión regular. Es decir. Salida:

User,City,AverageRating 
Jim,New York,3.75 
Jim,London,2 
Lisa,London,3.75 

podría escribir un script cerdo de la siguiente manera:

Data = LOAD 'data.txt' USING PigStorage(',') AS (
    user:chararray, city:chararray, restaurant:charray, rating:float 
); 

PerUserCity = GROUP Data BY (user, city); 

ResultSet = FOREACH PerUserCity { 
    GENERATE group.user, group.city, AVG(Data.rating); 
} 

Sin embargo tengo curiosidad si puedo primer grupo del grupo más alto nivel (los usuarios) y el grupo luego sub siguiente nivel (las ciudades) más tarde, es decir,

PerUser = GROUP Data BY user; 

Intermediate = FOREACH PerUser { 
    B = GROUP Data BY city; 
    GENERATE group AS user, B; 
} 

me sale:

Error during parsing. 
Invalid alias: GROUP in { 
    group: chararray, 
    Data: { 
    user: chararray, 
    city: chararray, 
    restaurant: chararray, 
    rating: float 
    } 
} 

¿Alguien ha intentado esto con éxito? ¿Simplemente no es posible agrupar dentro de una FOREACH?

Mi objetivo es hacer algo como:

ResultSet = FOREACH PerUser { 
    FOREACH City { 
     GENERATE user, city, AVG(City.rating) 
    } 
} 

Respuesta

8

Actualmente las operaciones permitidas son DISTINCT, FILTER, LIMIT, y ORDER BY dentro de un FOREACH.

Por ahora, agrupar directamente por (usuario, ciudad) es la mejor manera de hacer lo que usted dice.

+0

enlace se ha roto el hombre –

2

Las notas de la versión de Pig 0.10 sugieren que las operaciones anidadas de FOREACH son now supported.

+0

Gracias. ¿Por qué se requieren dos GENERATE en el bloque interno? –

+0

Retractando mi sugerencia. Las notas de la versión sugieren que se puede hacer, pero no puedo hacer que funcione. – chriswynnyk

0
awdata = load 'data' using PigStorage(',') as (user:chararray , city:chararray , restaurant:chararray , rating:float); 
data = filter rawdata by user != 'User'; 

groupbyusercity = group data by (user,city); 

--describe groupbyusercity; 
--groupbyusercity: {group: (user: chararray,city: chararray),data: {(user: chararray,city: chararray,restaurant: chararray,rating: float)}} 

average = foreach groupbyusercity { 
    generate group.user,group.city,AVG(data.rating); 
} 

dump average; 
1

Prueba esto:

Records = load 'data_rating.txt' using PigStorage(',') as (user:chararray, city:chararray, restaurant:chararray, rating:float); 
grpRecs = group Records By (user,city); 
avgRating_Byuser_perCity = foreach grpRecs generate AVG(Records.rating) as average; 
Result = foreach avgRating_Byuser_perCity generate flatten(group), average; 
+2

Debe agregar una descripción de lo que este código logra y cómo lo hace. –

+0

Esto está mal ... Debe ser Registros = cargar 'data_rating.txt 'usando PigStorage (', ') como (usuario: chararray, city: chararray, restaurant: chararray, rating: float); grpRecs = group Records By (usuario, ciudad); avgRating_Byuser_perCity = foreach grpRecs generate aplana (grupo), AVG (Records.rating) como promedio; Resultado = volcado avgRating_Byuser_perCity; – Kumar

0

Agrupación por dos llaves y luego aplanar la estructura conduce al mismo resultado:

Carga de datos como lo hizo

Data = LOAD 'data.txt' USING PigStorage(',') AS (
    user:chararray, city:chararray, restaurant:charray, rating:float); 

Grupo de usuario y ciudad

ByUserByCity = GROUP Data BY (user, city); 

Agregue la calificación promedio de los grupos (puede agregar más, como COUNT (datos) como count_res) A continuación, aplaste la estructura del grupo a la original.

ByUserByCityAvg = FOREACH ByUserByCity GENERATE 
FLATTEN(group) AS (user, city), 
AVG(Data.rating) as user_city_avg; 

Resultados en:

Jim,London,2.0 
Jim,New York,3.75 
Lisa,London,3.75 
User,City, 
+0

Supongo que esto no responde a la pregunta – Kumar