Как я & ldquo; un & rdquo; -explode Spark dataframe [duplicate]

Или это:

print '{0:02d}'.format(1)

17
задан zero323 10 June 2016 в 00:17
поделиться

4 ответа

Самый простой способ сделать это как DataFrame - сначала собрать два списка, а затем использовать UDF - zip два списка вместе. Что-то вроде:

import org.apache.spark.sql.functions.{collect_list, udf}
import sqlContext.implicits._

val zipper = udf[Seq[(String, Double)], Seq[String], Seq[Double]](_.zip(_))

val df = Seq(
  ("john", "tomato", 1.99),
  ("john", "carrot", 0.45),
  ("bill", "apple", 0.99),
  ("john", "banana", 1.29),
  ("bill", "taco", 2.59)
).toDF("name", "food", "price")

val df2 = df.groupBy("name").agg(
  collect_list(col("food")) as "food",
  collect_list(col("price")) as "price" 
).withColumn("food", zipper(col("food"), col("price"))).drop("price")

df2.show(false)
# +----+---------------------------------------------+
# |name|food                                         |
# +----+---------------------------------------------+
# |john|[[tomato,1.99], [carrot,0.45], [banana,1.29]]|
# |bill|[[apple,0.99], [taco,2.59]]                  |
# +----+---------------------------------------------+
21
ответ дан David Griffin 28 August 2018 в 02:03
поделиться

С помощью функции struct используйте функцию struct для группировки столбцов, прежде чем собирать в виде списка:

import org.apache.spark.sql.functions.{collect_list, struct}
import sqlContext.implicits._

val df = Seq(
  ("john", "tomato", 1.99),
  ("john", "carrot", 0.45),
  ("bill", "apple", 0.99),
  ("john", "banana", 1.29),
  ("bill", "taco", 2.59)
).toDF("name", "food", "price")

df.groupBy($"name")
  .agg(collect_list(struct($"food", $"price")).as("foods"))
  .show(false)

Выходы:

+----+---------------------------------------------+
|name|foods                                        |
+----+---------------------------------------------+
|john|[[tomato,1.99], [carrot,0.45], [banana,1.29]]|
|bill|[[apple,0.99], [taco,2.59]]                  |
+----+---------------------------------------------+
31
ответ дан Felix Leipold 28 August 2018 в 02:03
поделиться

Возможно, лучший способ, чем функция zip (, так как UDF и UDAF очень плохи для производительности ), состоит в том, чтобы обернуть два столбца в Struct.

Возможно, это сработает:

df.select('name, struct('food, 'price).as("tuple"))
  .groupBy('name)
  .agg(collect_list('tuple).as("tuples"))
1
ответ дан lzagkaretos 28 August 2018 в 02:03
поделиться

Вот вариант, преобразовывая кадр данных в RDD карты, а затем вызывайте на нем groupByKey. Результатом будет список пар ключ-значение, где value - список кортежей.

df.show
+----+------+----+
|  _1|    _2|  _3|
+----+------+----+
|john|tomato|1.99|
|john|carrot|0.45|
|bill| apple|0.99|
|john|banana|1.29|
|bill|  taco|2.59|
+----+------+----+


val tuples = df.map(row => row(0) -> (row(1), row(2)))
tuples: org.apache.spark.rdd.RDD[(Any, (Any, Any))] = MapPartitionsRDD[102] at map at <console>:43

tuples.groupByKey().map{ case(x, y) => (x, y.toList) }.collect
res76: Array[(Any, List[(Any, Any)])] = Array((bill,List((apple,0.99), (taco,2.59))), (john,List((tomato,1.99), (carrot,0.45), (banana,1.29))))
2
ответ дан Psidom 28 August 2018 в 02:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: