Как использовать Spark SQL DataFrame с flatMap?

я использую API Spark Scala. У меня есть Spark SQL DataFrame (чтение из файла Avro) со следующей схемой:

root
|-- ids: array (nullable = true)
|    |-- element: map (containsNull = true)
|    |    |-- key: integer
|    |    |-- value: string (valueContainsNull = true)
|-- match: array (nullable = true)
|    |-- element: integer (containsNull = true)

по существу 2 столбца [ ids: List[Map[Int, String]], match: List[Int] ]. Пример данных, который выглядит так:

[List(Map(1 -> a), Map(2 -> b), Map(3 -> c), Map(4 -> d)),List(0, 0, 1, 0)]
[List(Map(5 -> c), Map(6 -> a), Map(7 -> e), Map(8 -> d)),List(1, 0, 1, 0)]
...

то, что я хотел бы сделать, это flatMap() каждая строка для создания 3 столбцов [id, свойства, матч]. Используя приведенные выше 2 строки в качестве входных данных мы получить:

[1,a,0]
[2,b,0]
[3,c,1]
[4,d,0]
[5,c,1]
[6,a,0]
[7,e,1]
[8,d,0]
...

а то groupBy на String свойства (например: a, b,...) для производства count("property") и sum("match"):

 a    2    0
 b    1    0
 c    2    2
 d    2    0
 e    1    1

Я хотел бы сделать что-то вроде:

val result = myDataFrame.select("ids","match").flatMap( 
    (row: Row) => row.getList[Map[Int,String]](1).toArray() )
result.groupBy("property").agg(Map(
    "property" -> "count",
    "match" -> "sum" ) )

проблема в том, что flatMap преобразует фрейм данных в RDD. Есть ли хороший способ сделать flatMap введите операцию, за которой следует groupBy использование фреймов данных?

2 ответов


что значит flatMap вы этого хотите? Он преобразует каждую входную строку в 0 или более строк. Он может отфильтровать их или добавить новые. В SQL, чтобы получить ту же функциональность, которую вы используете join. Можете ли вы сделать то, что вы хотите сделать с join?

кроме того, вы также можете посмотреть Dataframe.explode, который является своеобразной join (вы можете легко создать свой собственный explode путем присоединения фрейма данных к UDF). explode принимает один столбец в качестве входных данных и позволяет разделять его или преобразуйте его в несколько значений, а затем join исходная строка возвращается в новые строки. Итак:

user      groups
griffin   mkt,it,admin

может стать:

user      group
griffin   mkt
griffin   it
griffin   admin

поэтому я бы сказал, взгляните на DataFrame.explode и если это не поможет вам легко, попробуйте присоединиться к UDFs.


мой SQL немного ржавый, но один из вариантов в вашем flatMap для создания списка объектов строк, а затем вы можете преобразовать полученный RDD обратно в фрейм данных.