Scala Spark DataFrame不尊重模式,将所有内容都视为字符串
我正面临着一个问题,这个问题我已经很久没有解决了Scala Spark DataFrame不尊重模式,将所有内容都视为字符串,scala,apache-spark,apache-spark-sql,apache-spark-mllib,scala-collections,Scala,Apache Spark,Apache Spark Sql,Apache Spark Mllib,Scala Collections,我正面临着一个问题,这个问题我已经很久没有解决了 我使用的是Spark 1.4和Scala 2.10。我现在无法升级(大型分布式基础架构) 我有一个有几百列的文件,其中只有两列是字符串,其余都是长的。我想将此数据转换为标签/特征数据框 我已经能够把它转换成LibSVM格式 我只是无法将其转换为标签/功能格式 原因是 如图所示,我无法使用toDF() 它在1.4中不受支持 因此,我首先将TXT文件转换为一个数据帧,在其中我使用了类似这样的内容 def getColumnDType(columnN
def getColumnDType(columnName:String):StructField = {
if((columnName== "strcol1") || (columnName== "strcol2"))
return StructField(columnName, StringType, false)
else
return StructField(columnName, LongType, false)
}
def getDataFrameFromTxtFile(sc: SparkContext,staticfeatures_filepath: String,schemaConf: String) : DataFrame = {
val sfRDD = sc.textFile(staticfeatures_filepath)//
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
// reads a space delimited string from application.properties file
val schemaString = readConf(Array(schemaConf)).get(schemaConf).getOrElse("")
// Generate the schema based on the string of schema
val schema =
StructType(
schemaString.split(" ").map(fieldName => getSFColumnDType(fieldName)))
val data = sfRDD
.map(line => line.split(","))
.map(p => Row.fromSeq(p.toSeq))
var df = sqlContext.createDataFrame(data, schema)
//schemaString.split(" ").drop(4)
//.map(s => df = convertColumn(df, s, "int"))
return df
}
df.na.drop()df.printSchema()
时,我得到了如下完美的模式
根目录
|--随机项:长(可空=假)
|--strcol1:字符串(nullable=false)
|--标签:长(nullable=false)
|--strcol2:字符串(nullable=false)
|--f1:长(可为空=假)
|--f2:长(可空=假)
|--f3:长(可空=假)
以此类推,直到大约300英尺
但是,令人伤心的是,无论我尝试用df做什么(见下文),我总是得到一个ClassCastException(java.lang.String不能转换为java.lang.Long)
所以,糟糕的是,尽管模式中说的是Long,df仍然在内部将所有内容都视为字符串
编辑
添加一个简单的示例
假设我有一个这样的文件
1,A,20,P,-99,1,0,0,8,1,1,1,1131153
1,B,23,P,-99,0,1,0,7,1,1,0,165543
1,C,24,P,-99,0,1,0,9,1,1,1,1,1262149
1,D,7,P,-99,0,0,8,1,1,1,1,1458759
及
sf schema=f0 strCol1 f1 strCol2 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11
(列名实际上并不重要,因此您可以忽略此详细信息)
我所要做的就是创建一个标签/特性类型的数据框,其中第3列成为标签,第5列到第11列成为特性[Vector]列。这样我就可以按照中的其余步骤进行操作
我也像zero323建议的那样铸造了这些柱
val types = Map("strCol1" -> "string", "strCol2" -> "string")
.withDefault(_ => "bigint")
df = df.select(df.columns.map(c => df.col(c).cast(types(c)).alias(c)): _*)
df = df.drop("f0")
df = df.drop("strCol1")
df = df.drop("strCol2")
但是assert和VectorAssembler仍然失败。
featureColumns=数组(“f2”、“f3”、“f11”)
这就是我拿到df后想做的整个序列
var transformeddf = new VectorAssembler()
.setInputCols(featureColumns)
.setOutputCol("features")
.transform(df)
transformeddf.show(2)
transformeddf = new StringIndexer()
.setInputCol("f1")
.setOutputCol("indexedF1")
.fit(transformeddf)
.transform(transformeddf)
transformeddf.show(2)
transformeddf = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(5)
.fit(transformeddf)
.transform(transformeddf)
ScalaIDE的异常跟踪-当它到达VectorAssembler时,如下所示
java.lang.ClassCastException:java.lang.String不能转换为java.lang.Long
在scala.runtime.BoxesRunTime.unbxtolong(BoxesRunTime.java:110)中
在scala.math.Numeric$LongIsIntegral$.toDouble处(Numeric.scala:117)
位于org.apache.spark.sql.catalyst.expressions.Cast$$anonfun$castToDouble$5.apply(Cast.scala:364)
位于org.apache.spark.sql.catalyst.expressions.Cast$$anonfun$castToDouble$5.apply(Cast.scala:364)
位于org.apache.spark.sql.catalyst.expressions.Cast.eval(Cast.scala:436)
位于org.apache.spark.sql.catalyst.expressions.Alias.eval(namedExpressions.scala:118)
位于org.apache.spark.sql.catalyst.expressions.CreateStruct$$anonfun$eval$2.apply(complexTypes.scala:75)
位于org.apache.spark.sql.catalyst.expressions.CreateStruct$$anonfun$eval$2.apply(complexTypes.scala:75)
位于scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
位于scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
位于scala.collection.mutable.resizeblearray$class.foreach(resizeblearray.scala:59)
位于scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
位于scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
位于scala.collection.AbstractTraversable.map(Traversable.scala:105)
位于org.apache.spark.sql.catalyst.expressions.CreateStruct.eval(complexTypes.scala:75)
位于org.apache.spark.sql.catalyst.expressions.CreateStruct.eval(complexTypes.scala:56)
位于org.apache.spark.sql.catalyst.expressions.ScalaUdf$$anonfun$2.apply(ScalaUdf.scala:72)
位于org.apache.spark.sql.catalyst.expressions.ScalaUdf$$anonfun$2.apply(ScalaUdf.scala:70)
位于org.apache.spark.sql.catalyst.expressions.ScalaUdf.eval(ScalaUdf.scala:960)
位于org.apache.spark.sql.catalyst.expressions.Alias.eval(namedExpressions.scala:118)
在org.apache.spark.sql.catalyst.expressions.解释器mutableprojection.apply上(Projection.scala:68)
在org.apache.spark.sql.catalyst.expressions.解释器mutableprojection.apply上(Projection.scala:52)
在scala.collection.Iterator$$anon$11.next(Iterator.scala:328)
在scala.collection.Iterator$$anon$11.next(Iterator.scala:328)
位于scala.collection.Iterator$$anon$10.next(Iterator.scala:312)
位于scala.collection.Iterator$class.foreach(Iterator.scala:727)
位于scala.collection.AbstractIterator.foreach(迭代器.scala:1157)
在scala.collection.generic.growtable$class.$plus$plus$eq(growtable.scala:48)
在scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:103)
在scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:47)
在scala.collection.TraversableOnce$class.to处(TraversableOnce.scala:273)
在scala.collection.AbstractIterator.to(Iterator.scala:1157)
在scala.collection.TraversableOnce$class.toBuffer处(TraversableOnce.scala:265)
位于scala.collection.AbstractIterator.toBuffer(Iterator.scala:1157)
位于scala.collection.TraversableOnce$class.toArray(TraversableOnce.scala:252)
位于scala.collection.AbstractIterator.toArray(Iterator.scala:1157)
位于org.apache.spark.sql.execution.SparkPlan$$anonfun$3.apply(SparkPlan.scala:143)
位于org.apache.spark.sql.execution.SparkPlan$$anonfun$3.apply(SparkPlan.scala:143)
位于org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1767)
位于org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1767)
位于org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:63)
位于org.apache.spark.scheduler.Task.run(Task.scala:70)
在org。
val types = Map("strCol1" -> "string", "strCol2" -> "string")
.withDefault(_ => "bigint")
df = df.select(df.columns.map(c => df.col(c).cast(types(c)).alias(c)): _*)
df = df.drop("f0")
df = df.drop("strCol1")
df = df.drop("strCol2")
var transformeddf = new VectorAssembler()
.setInputCols(featureColumns)
.setOutputCol("features")
.transform(df)
transformeddf.show(2)
transformeddf = new StringIndexer()
.setInputCol("f1")
.setOutputCol("indexedF1")
.fit(transformeddf)
.transform(transformeddf)
transformeddf.show(2)
transformeddf = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(5)
.fit(transformeddf)
.transform(transformeddf)
val rows = sc.textFile(staticfeatures_filepath)
.map(line => Row.fromSeq(line.split(",")))
val schema = StructType(
schemaString.split(" ").map(
columnName => StructField(columnName, StringType, false)
)
)
val df = sqlContext.createDataFrame(rows, schema)
import org.apache.spark.sql.types.{LongType, StringType}
val types = Map("strcol1" -> StringType, "strcol2" -> StringType)
.withDefault(_ => LongType)
val casted = df.select(df.columns.map(c => col(c).cast(types(c)).alias(c)): _*)
val transformeddf = new VectorAssembler()
.setInputCols(featureColumns)
.setOutputCol("features")
.transform(casted)
// As originally
val schema = StructType(
schemaString.split(" ").map(fieldName => getSFColumnDType(fieldName)))
val df = sqlContext
.read.schema(schema)
.format("com.databricks.spark.csv")
.option("header", "false")
.load(staticfeatures_filepath)