【问题标题】:Programmatically add column names to Spark DataFrame built from an RDD以编程方式将列名添加到从 RDD 构建的 Spark DataFrame
【发布时间】:2018-03-06 00:17:04
【问题描述】:

我有一个没有标题的管道分隔文本文件,并且行有不同数量的列(有些行是类型 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 DataFrame,但拆分返回的是单个数组,而不是 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?

【问题讨论】:

  • 您所要做的就是将 400 列数据放在文件顶部至少一个,然后使用 sqlContext api 将数据读入数据帧并稍后更改标题名称和数据类型。我猜就是这样
  • 数据文件中的某些行是 200 个不同的列,但是
  • 如果你可以修改文本文件,使400列数据先出现,那么在200列中读取的字段不足的地方将放置null

标签: scala apache-spark spark-dataframe


【解决方案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))))

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

【讨论】:

  • 正如你所说,Array[String] 是一个对象,这就是split 返回的内容。如果没有Seq,它仍然是一个带有Array[String] 单列的RDD,并且会引发相同的错误。我在测试可能的解决方案时不小心把Seq 放进去了
  • 是的,你是对的@KyleHeuton,我已经更新了下一个解决方案的答案,即通过创建模式
  • 有效!我希望我可以在这里使用 SparkSession 的inferSchema 的一些能力,但这可能是我能以这种方式处理数据的最好方法。正如您所说,最好的解决方案可能是拆分数据。如果没有其他令人惊奇的事情发生,我会在一天左右的时间内接受这个答案
  • 您能否像我在问题中的 cmets 中所说的那样调整您的数据,以便 400 列数据进入管道分隔文件。如果是,那么您可以按照我已经说过的那样尝试:)
  • 两者的 200 个列名是否相同?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 2012-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
相关资源
最近更新 更多