将RDD [String]转换为数据帧

时间:2019-05-02 08:27:59

标签: scala apache-spark dataframe rdd

我有以下形式的RDD [String]:

VAR1,VAR2,VAR3,VAR4, ...
  a ,  b ,  c ,  d , ...
  e ,  f ,  g ,  h , ...

这意味着第一行是我的标题逗号分隔,而接下来的所有行是我的数据,也是逗号分隔。

我的目的是将非结构化RDD转换为如下所示的DataFrame:

_____________________
|VAR1|VAR2|VAR3|VAR4| 
|----|----|----|----|
|  a |  b |  c |  d | 
|  e |  f |  g |  h | 

我尝试使用toDF()方法,该方法将RDD [tuples]转换为Dataframe。但是从我的变量数量(超过200个)来看,从RDD [String]到RDD [tuples]的转换听起来是不现实的。

另一种解决方法应该是使用该方法

sqlContext.createDataFrame(rdd, schema)

这需要将我的RDD [String]转换为RDD [Row],并将标头(RDD的第一行)转换为模式:StructType,但是我不知道如何创建该模式。

任何将RDD [String]转换为带有标头的Dataframe的解决方案都是很好的。

谢谢。

2 个答案:

答案 0 :(得分:3)

您还可以通过以下方式实现此结果:

val data = Seq(
  ("VAR1, VAR2, VAR3, VAR4"),
  ("a, b, c, d"),
  ("ae, f, g, h")
)

val dataDS = sc.parallelize(data).toDS
val result = spark.read.option("inferSchema","true").option("header","true").csv(dataDS)

result.printSchema

result.show

上面的输出是:

root
 |-- VAR1: string (nullable = true)
 |--  VAR2: string (nullable = true)
 |--  VAR3: string (nullable = true)
 |--  VAR4: string (nullable = true)

+----+-----+-----+-----+
|VAR1| VAR2| VAR3| VAR4|
+----+-----+-----+-----+
|   a|    b|    c|    d|
|  ae|    f|    g|    h|
+----+-----+-----+-----+

如果您的数据在其中一列(标题除外)中具有数字,则“ inferSchema”应正确地将该列推断为数字类型。 例如,将其用作输入数据:

val data = Seq(
  ("VAR1, VAR2, VAR3, VAR4"),
  ("a,   1, c, d"),
  ("ae, 10, g, h")
)

输出将是:

root
 |-- VAR1: string (nullable = true)
 |--  VAR2: double (nullable = true)
 |--  VAR3: string (nullable = true)
 |--  VAR4: string (nullable = true)

+----+-----+-----+-----+
|VAR1| VAR2| VAR3| VAR4|
+----+-----+-----+-----+
|   a|  1.0|    c|    d|
|  ae| 10.0|    g|    h|
+----+-----+-----+-----+

我希望这会有所帮助。

答案 1 :(得分:1)

可以从第一行创建模式:

val data = Seq(
  ("VAR1, VAR2, VAR3, VAR4"),
  ("a, b, c, d"),
  ("ae, f, g, h")
)
val rdd = sparkContext.parallelize(data).map(_.split(","))

val firstRow = rdd.first()
val schemaFields = firstRow.map(n => StructField(n, StringType, true))

val remaining = rdd.zipWithIndex().filter(_._2 > 0).keys.map(v => Row(v.toSeq: _*))
val result = spark.createDataFrame(remaining, StructType(schemaFields))
result.show(false)

输出为:

+----+-----+-----+-----+
|VAR1| VAR2| VAR3| VAR4|
+----+-----+-----+-----+
|a   | b   | c   | d   |
|ae  | f   | g   | h   |
+----+-----+-----+-----+