как работать с объединенным RDD

скажем, что у меня есть текстовый файл с именами 1.txt и 2.txt. 1.txt содержит

1,9,5
2,7,4
3,8,3

а 2.txt содержит

1,g,h
2,i,j
3,k,l

Итак, я присоединился к ним по их ключам (первый столбец):

val one = sc.textFile("1.txt").map{
  line => val parts = line.split(",",-1)
    (parts(0),(parts(1),parts(2)))
}

val one = sc.textFile("2.txt").map{
  line => val parts = line.split(",",-1)
    (parts(0),(parts(1),parts(2)))
}

Теперь, если я правильно понимаю, я получаю

(1,  (  (9,5), (g,h)  ))
(2,  (  (7,4), (i,j)  ))
(3,  (  (8,3), (k,l)  ))

Теперь предположим, что мне нужно просуммировать все значения второго столбца 1.txt,

  1. Как мне это сделать?

  2. Как мне обратиться ко второму столбцу 2.txt(т. е. g, i, k) в объединенном RDD?

  3. Есть ли хороший учебник по работе с RDD? Я искра (и scala) новичок.


person user2773013    schedule 09.07.2014    source источник


Ответы (1)


  1. присоединиться очень просто val joined = one.join(two) (заметил, что вы по какой-то причине назвали оба RDD one, предполагая, что вы хотели дать им разные имена)

  2. синтаксис кортежа в scala равен tuple._number, поэтому суммировать столбцы 1.txt, если joined - это объединенный RDD, который вы делаете val sum = joined.map(_._2._1._2.toInt).reduce(_+_) , возможно, вы захотите преобразовать его в long или даже BigInt на карте, если эти файлы действительно большие.

  3. Я бы сказал, что лучшие руководства по Spark — это их главный сайт, материал лагеря amp, и мне лично нравится просматривать источник и скаладок. Для scala "программирование в scala" - хорошее начало.

Вся программа, слегка переписанная для использования лучшего стиля Scala (отказ от ответственности, не эксперт по Scala)

val one = sc.textFile("1.txt").map{
  _.split(",", -1) match {
    case Array(a, b, c) => (a, ( b, c))
  }
}

val two = sc.textFile("2.txt").map{
    _.split(",", -1) match {
      case Array(a, b, c) => (a, (b, c)) 
    }
    //looks like these two map functions are the same, could refactor into a lambda or non member function
}

val joined = one.join(two)

val sum = joined.map {
     case (_, ((_, num2), (_, _))) => num2.toInt 
}.reduce(_ + _)
person aaronman    schedule 09.07.2014
comment
Возможно, более удобочитаемой альтернативой map(_._2._1._2.toInt) является map { case (id, ((num1, num2), (str1, str2))) => num2.toInt }. - person Daniel Darabos; 09.07.2014
comment
Ваш стиль был почти идеальным ... вы должны использовать () всякий раз, когда у вас есть однострочные лямбда-выражения, и предложение @DanielDarabos сделает все более читабельным. Наконец, вы должны ставить пробелы после запятых и между операторами. ... я постараюсь отредактировать ваш ответ - person samthebest; 09.07.2014
comment
О, и +1 за то, что не забыли использовать -1 в своем сплите - невероятно, как много людей забывают об этом! - person samthebest; 09.07.2014
comment
@DanielDarabos принял ваше предложение - person aaronman; 09.07.2014
comment
@samthebest большинство ваших правок были незначительными, но в следующий раз я прогоню свою программу через scalastyle перед отправкой :). Помимо того, что вы удалили мой отказ от ответственности, я не могу допустить, чтобы люди думали, что я эксперт по Scala. - person aaronman; 09.07.2014
comment
Если вы собираетесь использовать только num2, то просто оставьте остальные как _ ... и, пожалуйста, вставьте пробелы по крайней мере :) (пробелы не являются незначительным редактированием в реальных проектах, поскольку автоформатеры затем сломают git diff и может вызвать конфликты слияния кошмаров) - person samthebest; 09.07.2014
comment
всем БОЛЬШОЕ СПАСИБО!! Мне нравится комментарий @DanielDarabos о читабельности. Спасибо вам всем !! - person user2773013; 09.07.2014