Чтобы запустить функцию tabulate и which.max в sparkR

У меня есть DataFrame data в sparkR. Он содержит user = 12 311 12 320, ... и type = 1 2 3 4. У нас 10000 пользователей.

Например, у одного пользователя тип = 1 2 3 4 4 4 2 4. Я хочу найти наиболее распространенное целое число для этого пользователя. В R я могу решить это так

mostcommon <- which.max(tabulate(user$type))

учитывая, что «пользователь» был data.frame, а не DataFrame. Я хочу сделать это для всех пользователей в «данных». Один из способов сделать это так

u<- c()
for(j in 1:10000) {
id <- filter(data, data$user== j)
# For the jth user I make the data local to run the 
# which.max and tabulate functions
idlocal <- collect(id)
u[j] <- which.max(tabulate(idlocal$type))
}

Это работает в R/sparkR, и вы даете мне наиболее распространенный тип для всех пользователей. Но это требует времени, потому что я сделал данные локальными для запуска функций which.max и tabulate. Есть ли более умный и быстрый способ сделать это?

Кроме того, как можно найти два наиболее распространенных типа?


person Ole Petersen    schedule 01.09.2015    source источник


Ответы (1)


Возможно, это не лучшее решение, но оно работает:

Создать пример данных

localData <- data.frame(user = c(1,1,1,2,2,2),
                        type = c(1,2,2,3,3,2))

data <- createDataFrame(sqlContext, localData)

Сгруппируйте по пользователю, введите и подсчитайте, сколько раз это встречается (вроде таблицы)

groupedData <- groupBy(data, data$user, data$type)
aggregated  <- agg(groupedData, number = n(data$user))

Заказывайте по этому подсчитанному числу, так как это самый простой способ найти тип, который имеет максимальное вхождение.

arranged <- arrange(aggregated, desc(aggregated$number))

Снова сгруппируйте по пользователю и возьмите первое вхождение типа, которое является максимальным с тех пор, как мы его заказали.

regroupedData <- groupBy(arranged, arranged$user)
firstItems    <- agg(regroupedData, firstType = first(arranged$type), number = first(arranged$number))

Проверьте результаты

collect(firstItems)

Если теперь вам нужен второй наиболее часто встречающийся элемент, вы можете сначала удалить эти первые элементы.

firstDeleted <- except(arranged,firstItems)

И снова применить тот же метод

rearranged   <- arrange(firstDeleted, desc(firstDeleted$number))

reregroupedData <- groupBy(rearranged, rearranged$user)
secondItems     <- agg(reregroupedData, secondType = first(rearranged$type))

Удалить ненужный столбец и переименовать столбец firstItems$number ‹- NULL secondItems ‹- withColumnRenamed(secondItems, "user", "user2")

Для окончательного результата присоедините эти кадры данных (удалить столбец user2)

result <- join(firstItems,secondItems, firstItems$user == secondItems$user2)

result$user2 <- NULL

И снова проверить эти результаты

collect(result)
person Wannes Rosiers    schedule 01.09.2015
comment
Скажем, нам нужны два наиболее распространенных типа. Как это сделать? Возможно, удалив первый (упорядоченный тип $), а затем снова возьмите первый. - person Ole Petersen; 03.09.2015
comment
Вы хотите для каждого пользователя первые два типа? - person Wannes Rosiers; 03.09.2015
comment
Да, первые два типа, которые также будут наиболее распространенными типами. - person Ole Petersen; 03.09.2015
comment
У меня есть рабочий пример, но в нем слишком много символов для комментария. Он основан на функции exclude. Не могли бы создать новый или отредактировать свой вопрос? - person Wannes Rosiers; 04.09.2015
comment
Строка firstDeleted ‹- кроме(упорядочено,результат). Должен ли результат быть заменен на firstItems ? - person Ole Petersen; 04.09.2015
comment
Да, поменял. Спасибо - person Wannes Rosiers; 04.09.2015
comment
Когда я набираю «собрать (результат)», я получаю только один тип, но он должен отображать оба типа? - person Ole Petersen; 04.09.2015
comment
Он показывает один тип в строке, но у каждого пользователя есть две строки, следовательно, два типа. - person Wannes Rosiers; 04.09.2015
comment
На самом деле, когда вы присоединитесь к переименованию столбца secondItems и присоединитесь к firstItems и secondItems, вы, вероятно, получите то, что хотите. - person Wannes Rosiers; 05.09.2015
comment
Когда я набираю head(filter(firstItems, firstItems$user_id==1)) я получаю user_id=8966 и type=4 и number=1. Когда я набираю head(filter(secondItems, secondItems$user_id==1)) я получаю user_id=8966 и type=4. Когда я набираю заголовок (результат), первая строка имеет значение user_id = 8966 и тип = 4. Но «результат» должен содержать два типа в первой строке. - person Ole Petersen; 07.09.2015
comment
Теперь оба верхних результата присутствуют, я больше не добавлял число, в котором они встречаются, но это все еще возможно. - person Wannes Rosiers; 07.09.2015