我有“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))
这里有什么问题?
答案 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");