Spark:向csv文件添加列名失败

时间:2017-04-17 23:46:38

标签: scala csv apache-spark spark-dataframe

我有“a.txt”,它采用csv格式,并以制表符分隔:

16777216    16777471        -33.4940    143.2104
16777472    16778239    Fuzhou  26.0614 119.3061

然后我跑:

sc.textFile("path/to/a.txt").map(line => line.split("\t")).toDF("startIP", "endIP", "City", "Longitude", "Latitude")

我得到了:

  

java.lang.IllegalArgumentException:要求失败:数量   列不匹配。旧列名(1):值新列名   (5):startIP,endIP,City,Longitude,Latitude at   scala.Predef $ .require(Predef.scala:224)at   org.apache.spark.sql.Dataset.toDF(Dataset.scala:376)at at   org.apache.spark.sql.DatasetHolder.toDF(DatasetHolder.scala:40)...   47 elided

如果我刚跑:

res.map(line => line.split("\t")).take(2)

我得到了:

rdd: Array[Array[String]] = Array(Array(16777216, 16777471, "", -33.4940, 143.2104), Array(16777472, 16778239, Fuzhou, 26.0614, 119.3061))

这里有什么问题?

3 个答案:

答案 0 :(得分:3)

正如@ user7881163所述,发生错误是因为您的split生成了一个列,其值(因此Spark给出的value名称)是split生成的令牌数组。

但是,根据来自@ zero323的评论,如果您正在大规模操作,请确保使用版本collect @ user7881163使用(采用部分功能的版本),因为另一个更常用collect会将您的所有数据移至驱动程序并淹没该计算机。如果你没有大规模运营,为什么要使用Spark呢?

这是一种稍微不同的方法,也允许丢失城市数据:

sc.textFile("path/to/a.txt")
  .map(_.split("\t"))
  .map {
      case Array(startIP, endIP, city, longitude, latitude) => (startIP, endIP, Some(city), longitude, latitude)
      case Array(startIP, endIP, longitude, latitude) => (startIP, endIP, None, longitude, latitude)
  }.toDF("startIP", "endIP", "City", "Longitude", "Latitude")

答案 1 :(得分:1)

尝试:

sc
  .textFile("path/to/a.txt")
  .map(line => line.split("\t"))
  .collect { case Array(startIP, endIP, City, Longitude, Latitude) => 
    (startIP, endIP, City, Longitude, Latitude) 
  }.toDF("startIP", "endIP", "City", "Longitude", "Latitude")

或只使用csv来源:

spark.read.option("delimiter", "\t").csv("path/to/a.txt")

您当前的代码会创建一个DataFrame,其中包含array<string>类型的单个列。这就是你传递5个名字时失败的原因。

答案 2 :(得分:0)

你可以尝试这个例子:

dataDF = sc.textFile("filepath").map(x=>x.split('\t').toDF();

data = dataDF.selectExpr("_1 as startIP", "_2 as endIP", "_3 as City", "_4 as Longitude", "_5 as Latitude");