Как группировать и считать RDD [Map [Array [Int], Int]]? - PullRequest
1 голос
/ 27 апреля 2020

У меня есть некоторые входные данные как RDD[Map[Array[String],String]]:

(Map(Array[c1, a1] -> Y),
Map(Array[a1] ->Y), 
Map(Array[c1, a1] ->N),
Map[Array[a1] ->N),
Map[Array[a1] ->Y))

Я хочу группировать по ключу, значению и масштабировать каждое значение по ключу. В качестве вывода я хочу создать RDD[Map[Array[String],Int]] следующим образом:

(Map(Array[c1, a1, Y] -> 0.5),
(Map(Array[c1, a1, N] -> 0.5),
(Map(Array[a1 ,Y ] -> 0.66), 
(Map(Array[a1, N] -> 0.33))

Я использую Scala и Spark для больших данных.

1 Ответ

0 голосов
/ 27 апреля 2020

Используя СДР, одним из способов решения этой проблемы будет использование reduceByKey для сбора списка всех значений (в данном случае Y и N). Затем мы можем вычислить пропорцию каждого значения в зависимости от ключа.

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

rdd
  .map(m => (m.keys.head, m.values.toList))
  .reduceByKey(_ ::: _)                         // Collect a list with Ys and Ns
  .flatMap{ case(k,v) =>
    val uniqueCount = v.groupBy(identity)       // Unique values and their counts
      .mapValues(_.size) 
    val totalCount = v.size.toFloat             // Total count

    // Create return list with Maps
    uniqueCount.map{case (uniqueVal, uniqueCount) => Map((k :+ uniqueVal) -> uniqueCount / totalCount)}
}

Результат:

Map(List(c1, a1, Y) -> 0.5)
Map(List(c1, a1, N) -> 0.5)
Map(List(a1, Y) -> 0.6666667)
Map(List(a1, N) -> 0.33333334)
...