2016-08-19 3 views
1

Мне нужно выполнить простую группировку данных в Spark (Scala). В частности, это мой исходные данные:Эффективная группировка данных в Spark

1, a, X 
1, b, Y 
2, a, Y 
1, a, Y 

val seqs = Seq((1, "a", "X"),(1, "b", "Y"),(2, "a", "Y"),(1, "a", "Y")) 

Мне нужно сгруппировать его по первому ключу следующим образом:

1, (a, X), (b, Y), (a, Y) 
2, (a, Y) 

Мой первоначальный IDIA был использовать DataFrame и groupBy, но я читал, что это операция очень дорогостоящая и требует полной перестановки всех данных.

Итак, что является менее дорогостоящим вариантом для группировки? Будет дан конкретный пример.

+0

но группа именно то, что вы хотели - и параллельная обработка - это сила искры, поэтому вы можете делать groupBy в RDD или Dataframe. Альтернативой является сокращение, которое намного более эффективно, но проблема в том, что в конце вы остаетесь с 1 парой значений ключа для каждой группы. – GameOfThrows

+0

Вы не можете группировать вещи по разделам, не делая тасование. Подумайте, куда нужно идти. Это дорого, потому что это обязательно дорого. –

ответ

1

потенциально вы можете сделать что-то вроде этого:

val rdd = sc.parallelize(List((1, "a", "X"),(1, "b", "Y"),(2, "a", "Y"),(1, "a", "Y"))) 
    val mapping = rdd.map(x=>(x._1,List((x._2,x._3)))) 
    val result = mapping.reduceByKey((x,y) => (x ++ y)) 

Это использует reduceByKey, но проблема со всеми сократить процесс, вы должны в конечном итоге с 1 парой ключей значение для каждой группы. Таким образом, в этом случае вам нужно явно преобразовать каждое из ваших значений в списки, поэтому процесс сокращения может затем объединить их.

Вы можете также рассмотреть глядя на combineByKey, который использует внутренний процесс снижения

====== ====== EDIT

Как zero323 отметил, сократить здесь не будет увеличиваться эффективности и наоборот - процесс потеряет оптимизацию groupByKey.

+0

Спасибо. Просто небольшой вопрос (я, вероятно, пропустил эту деталь в своем объяснении). Мои реальные данные находятся в формате RDD [String]. Поэтому я делаю 'val splititted = rdd.map (line => line.split (", "))', чтобы получить определенные значения, например. '1',' a', 'X'. Переменная 'splitted' имеет тип' RDD [Array [String]] '. Как я должен применять 'reduceByKey' к' splitted'? – HackerDuck

+0

@HackerDuck вам необходимо отобразить массив строк в структуру (Int, String, String) через класс case или что-то в этом роде - это общая практика, чтобы сопоставить его через класс case, поскольку он также действует как схема при преобразовании он находится в Dataframe (если вы этого желаете). – GameOfThrows

+0

Что означает '(x ++ y)'? – HackerDuck

Смежные вопросы