以编程方式将列名添加到从RDD构建的Spark DataFrame

时间:2018-03-05 15:36:05

标签: scala apache-spark spark-dataframe

我有一个没有标题的竖线分隔文本文件,并且行的列数不同(某些行的类型为A,列数为400列,其他行类型为B,其中包含200列,所以我需要先将它们分开):

val textFileRaw = sc.textFile("./data.txt")
val textFile = textFileRaw.map(line => line.split("\\|", -1))
val dataA = textFile.filter(line => line(0) == "A")
val dataB = textFile.filter(line => line(0) == "B")

现在我想将这些RDD转换为Spark DataFrames,但拆分返回单个数组,而不是400或200个不同的值。这会导致以下错误:

# ANames are my column names, length=400
val ANames = Array("Row ID", "City", "State", ...)
val dataADF = dataA.toDF(ANames: _*)

Name: java.lang.IllegalArgumentException
Message: requirement failed: The number of columns doesn't match.
Old column names (1): value
New column names (400): Row ID, City, State ...

This question面临同样的问题,但所有答案建议手动指定从数组到元组的映射,在数百列的情况下,这不是很好。

我认为如果我使用Spark's csv loader,我可以让它工作,但这对我的数据不起作用,因为行具有不同数量的字段(它不是真正的csv文件)。解决方法是首先拆分文件,编写格式正确的csv的新文件,然后使用csv加载程序,但我想尽可能避免这种情况。如何将这些RDD转换为带有命名列的DataFrame?

1 个答案:

答案 0 :(得分:1)

您应该创建一个架构并使用SQLContext.createDataFrame api作为

val dataA = textFile.filter(line => line(0) == "A")
val ANames = Array("Row ID", "City", "State", "kjl")
val dataADF = sqlContext.createDataFrame(dataA.map(Row.fromSeq(_)), StructType(ANames.map(StructField(_, StringType, true))))

它应该工作。但请注意,我已将所有<​​em>数据类型用作StringType()。您可以根据需要进行更改。