将Spark的DataFrame列转换为Scala中的List [String]

时间:2016-10-17 21:22:38

标签: scala csv apache-spark dataframe spark-dataframe

我正在处理Movie Lens数据集。在csv个文件中,数据结构为:

movieId movieTitle genres

genres再次是|个分隔值的列表,该字段可以为空。

我正在尝试获取所有genres的唯一列表,以便我可以重新排列数据如下:

movieId movieTitle genre1 genre2 ... genreN

genregenre1 | genre2的行如下所示:

1 Title1 1 1 0 ... 0

到目前为止,我已经能够使用以下代码阅读csv文件:

val conf         = new SparkConf().setAppName(App.name).setMaster(App.sparkMaster)
val context      = new SparkContext(conf)
val sparkSession = SparkSession.builder()
                   .appName(App.name)
                   .config("header", "true")
                   .config(conf = conf)
                   .getOrCreate()

val movieFrame: DataFrame = sparkSession.read.csv(moviesPath)

如果我尝试这样的话:

movieFrame.rdd.map(row ⇒ row(2).asInstanceOf[String]).collect()

然后我得到以下异常:

java.lang.ClassNotFoundException: com.github.babbupandey.ReadData$$anonfun$1

然后,我还尝试使用以下代码显式提供架构:

val moviesSchema: StructType = StructType(Array(StructField("movieId", StringType, nullable = true),
                                                        StructField("title", StringType, nullable = true),
                                                        StructField("genres", StringType, nullable = true)))

并尝试:

val movieFrame: DataFrame = sparkSession.read.schema(moviesSchema).csv(moviesPath)

然后我得到了同样的例外。

我有什么方法可以将genres设置为ListSet,以便我可以进一步按下数据到所需的格式?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

以下是我如何获得一系列类型:

val genreList: Array[String] = for (row <- movieFrame.select("genres").collect) yield row.getString(0)
val genres: Array[String] =  for {
        g ← genreList
        genres ← g.split("\\|")
    } yield genres
val genreSet : Set[String] = genres.toSet

答案 1 :(得分:-1)

这适用于给出一个数组[Array [String]]

    val genreLst = movieFrame.select("genres").rdd.map(r =>     r(0).asInstanceOf[String].split("\\|").map(_.toString).distinct).collect()

获取Array [String]

    val genres = genreLst.flatten

    val genreLst = movieFrame.select("genres").rdd.map(r => r(0).asInstanceOf[String].split("\\|").map(_.toString).distinct).collect().flatten