我正在阅读csv文件,需要创建一个RDDSchema
我使用sqlContext.csvFile
val testfile = sqlContext.csvFile("file")
testfile.registerTempTable(testtable)
我想更改选择某些字段并返回这些字段的RDD类型 例如:class Test(ID:String,order_date:Date,Name:String,value:Double)
使用sqlContext.sql(“选择col1,col2,col3,col4 FROM ...)
val testfile = sqlContext.sql("Select col1, col2, col3, col4 FROM testtable).collect
testfile.getClass
Class[_ <: Array[org.apache.spark.sql.Row]] = class [Lorg.apache.spark.sql.Row;
所以我想将col1更改为double,将col2更改为日期,将column3更改为string? 有没有办法在sqlContext.sql中执行此操作,或者我必须对结果运行map函数,然后将其转回RDD .. 我尝试在一个语句中执行该项目,我收到此错误:
val old_rdd : RDD[Test] = sqlContext.sql("SELECT col, col2, col3,col4 FROM testtable").collect.map(t => (t(0) : String ,dateFormat.parse(dateFormat.format(1)),t(2) : String, t(3) : Double))
我遇到的问题是赋值不会导致RDD [Test],其中Test是一个定义的类
错误是map命令是作为Array Class而不是RDD Class
出现的 found : Array[edu.model.Test]
[error] required: org.apache.spark.rdd.RDD[edu.model.Test]
答案 0 :(得分:0)
假设你有一个这样的案例类:
case class Test(
ID: String, order_date: java.sql.Date, Name: String, value: Double)
由于您使用csvFile
使用默认参数加载数据,因此它不执行任何架构推断,并且您的数据存储为纯字符串。让我们假设没有其他字段:
val df = sc.parallelize(
("ORD1", "2016-01-02", "foo", "2.23") ::
("ORD2", "2016-07-03", "bar", "9.99") :: Nil
).toDF("col1", "col2", "col3", "col4")
由于多种原因,您尝试使用地图是错误的:
Row.apply
不仅属于Int => Any
类型,而且您的数据表中不包含任何Double
值collect
(这里没有意义)您将所有数据提取到驱动程序,结果是本地Array
而非RDD
(String, Date, String, Double)
显然不是Test
处理此问题的一种方法:
import org.apache.spark.sql.Row
import org.apache.spark.rdd.RDD
val casted = df.select(
$"col1".alias("ID"),
$"col2".cast("date").alias("order_date"),
$"col3".alias("name"),
$"col4".cast("double").alias("value")
)
val tests: RDD[Test] = casted.map {
case Row(id: String, date: java.sql.Date, name: String, value: Double) =>
Test(id, date, name, value)
}
您也可以尝试使用新的Dataset
API,但它远非稳定:
casted.as[Test].rdd