Могу ли я создать вложенные пакеты, используя вложенные операторы FOREACH в Pig Latin? - PullRequest
7 голосов
/ 08 февраля 2011

Допустим, у меня есть набор данных обзоров ресторанов:

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

И я хочу составить список по пользователям и городам среднего обзора. То есть выход:

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

Я мог бы написать скрипт Pig следующим образом:

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);
}

Однако мне любопытно, могу ли я сначала сгруппировать группу более высокого уровня (пользователей), а затем подгруппировать следующий уровень (города): т.е.

PerUser = GROUP Data BY user;

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

Я получаю:

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

Кто-нибудь пробовал это с успехом? Разве просто невозможно группировать в FOREACH?

Моя цель - сделать что-то вроде:

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

Ответы [ 5 ]

8 голосов
/ 11 февраля 2011

В настоящее время разрешены операции DISTINCT, FILTER, LIMIT и ORDER BY внутри FOREACH .

На данный момент группировка напрямую (пользователь, город) - это хороший способ сделать, как вы сказали.

2 голосов
/ 27 декабря 2012

Примечания к выпуску для Pig версии 0.10 предполагают, что вложенные операции FOREACH теперь поддерживаются .

1 голос
/ 18 мая 2014

Попробуйте это:

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;
0 голосов
/ 21 мая 2014

Группировка по двум ключам, а затем выравнивание структуры приводит к тому же результату:

Загрузка данных, как вы сделали

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

Группировка по пользователю и городу

 ByUserByCity = GROUP Data BY (user, city);

Добавление среднего рейтинга по группам (вы можете добавить больше, например COUNT (Данные) как count_res) Затем сведите структуру группы к исходной.

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

Результаты:

Jim,London,2.0
Jim,New York,3.75
Lisa,London,3.75
User,City,
0 голосов
/ 29 апреля 2014
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;
...