我有一个文本文件,我可以读取该文本文件并进行解析以创建数据框。但是,列amount
和code
应该是IntegerTypes。这是我所拥有的:
def getSchema: StructType = {
StructType(Seq(
StructField("carrier", StringType, false),
StructField("amount", StringType, false),
StructField("currency", StringType, false),
StructField("country", StringType, false),
StructField("code", StringType, false),
))
}
def getRow(x: String): Row = {
val columnArray = new Array[String](5)
columnArray(0) = x.substring(40, 43)
columnArray(1) = x.substring(43, 46)
columnArray(2) = x.substring(46, 51)
columnArray(3) = x.substring(51, 56)
columnArray(4) = x.substring(56, 64)
Row.fromSeq(columnArray)
}
因为我已定义Array[String]
,所以列只能是StringTypes,而不能是String和Integer的各种。为了详细解释我的问题,发生了什么:
首先,我创建一个空的数据框:
var df = spark.sqlContext.createDataFrame(spark.sparkContext.emptyRDD[Row], getSchema)
然后我有一个for循环,遍历所有目录中的每个文件。注意:我需要验证每个文件,并且无法一次读取所有文件。
for (each file parse):
df2 = spark.sqlContext.createDataFrame(spark.sparkContext.textFile(inputPath)
.map(x => getRow(x)), schema)
df = df.union(df2)
我现在拥有所有文件的完整数据框。但是,列amount
和code
仍然是StringTypes。如何使它们成为IntegerTypes?
请注意:在for循环过程中,我无法转换列,因为这会花费很多时间。我想保持当前结构尽可能的相似。在for循环的最后,我可以将这些列转换为IntegerTypes,但是,如果该列包含的值不是Integer怎么办?我希望列不为NULL。
是否有一种方法可以使两个指定的列成为IntegerType,而无需对代码进行大量更改?
答案 0 :(得分:2)
使用数据集怎么办?
首先创建一个对数据建模的案例类:
case class MyObject(
carrier: String,
amount: Double,
currency: String,
country: String,
code: Int)
创建另一个案例类,将第一个案例类附加其他信息(潜在错误,源文件):
case class MyObjectWrapper(
myObject: Option[MyObject],
someError: Option[String],
source: String
)
然后创建一个解析器,从myObject中的文件转换一行:
object Parser {
def parse(line: String, file: String): MyObjectWrapper = {
Try {
MyObject(
carrier = line.substring(40, 43),
amount = line.substring(43, 46).toDouble,
currency = line.substring(46, 51),
country = line.substring(51, 56),
code = line.substring(56, 64).toInt)
} match {
case Success(objectParsed) => MyObjectWrapper(Some(objectParsed), None, file)
case Failure(error) => MyObjectWrapper(None, Some(error.getLocalizedMessage), file)
}
}
}
最后,解析您的文件:
import org.apache.spark.sql.functions._
val ds = files
.filter( {METHOD TO SELECT CORRECT FILES})
.map( { GET INPUT PATH FROM FILES} )
.map(path => spark.read.textFile(_).map(Parser.parse(_, path))
.reduce(_.union(_))
这应该为您提供具有所需类型和API的数据集[MyObjectWrapper]。
然后,您可以解析那些内容:
ds.filter(_.someError == None)
或者接受您未能解析的内容(用于调查):
ds.filter(_.someError != None)