Скала Трансформация и действие - PullRequest
0 голосов
/ 19 марта 2019

У меня есть список RDD [(String, List [Int])], подобный List ((«A», List (1,2,3,4)), («B», List (5,6,7))))

Как преобразовать их в список ((«A», 1), («A», 2), («A», 3), («A», 4), («B ", 5), (" B ", 6), (" B ", 7))

Тогда действие будет уменьшаться по ключу и генерировать результат, подобный List ((" A ", 2.5) ("B ", 6))

Я пытался использовать карту (e => List (e._1, e._2)), но это не дает желаемого результата.

Где 2,5 - среднее значение для«А» и «6» - среднее для «Б»Заранее спасибо

Ответы [ 3 ]

1 голос
/ 19 марта 2019

Если вы хотите получить среднее значение каждого списка в конце, то нет необходимости разбивать их на отдельные элементы с flatMap.Выполнение этого с большим списком приведет к ненужной перестановке большого количества данных с большим набором данных.

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

val l = spark.sparkContext.parallelize(Seq(
  ("A", List(1, 2, 3, 4)),
  ("B", List(5, 6, 7))
))

val avg = l.map(r => {
    (r._1, (r._2.sum.toDouble / r._2.length.toDouble))
})

avg.collect.foreach(println)

Имейте в виду, что это не удастся, если любой из ваших списков 0 длина.Если у вас есть списки длиной 0, вам нужно будет поставить условие проверки на карту.

Приведенный выше код дает вам:

(A,2.5)
(B,6.0)
1 голос
/ 19 марта 2019

Вы можете попробовать взорваться ()

scala> val df = List(("A",List(1,2,3,4)),("B",List(5,6,7))).toDF("x","y")
df: org.apache.spark.sql.DataFrame = [x: string, y: array<int>]

scala> df.withColumn("z",explode('y)).show(false)
+---+------------+---+
|x  |y           |z  |
+---+------------+---+
|A  |[1, 2, 3, 4]|1  |
|A  |[1, 2, 3, 4]|2  |
|A  |[1, 2, 3, 4]|3  |
|A  |[1, 2, 3, 4]|4  |
|B  |[5, 6, 7]   |5  |
|B  |[5, 6, 7]   |6  |
|B  |[5, 6, 7]   |7  |
+---+------------+---+


scala> val df2 = df.withColumn("z",explode('y))
df2: org.apache.spark.sql.DataFrame = [x: string, y: array<int> ... 1 more field]

scala> df2.groupBy("x").agg(sum('z)/count('z) ).show(false)
+---+-------------------+
|x  |(sum(z) / count(z))|
+---+-------------------+
|B  |6.0                |
|A  |2.5                |
+---+-------------------+


scala>
1 голос
/ 19 марта 2019

Есть несколько способов получить то, что вы хотите. Вы также можете использовать для понимания , но самое первое, что пришло мне в голову, это реализация:

val l = List(("A", List(1, 2, 3)), ("B", List(1, 2, 3)))

val flattenList = l.flatMap {
  case (elem, _elemList) =>
    _elemList.map((elem, _))
}

Выход:

List((A,1), (A,2), (A,3), (B,1), (B,2), (B,3))

...