我有一个没有架构的数据框,每个列都存储为StringType,如:
ID | LOG_IN_DATE | USER
1 | 2017-11-01 | Johns
现在我创建了一个架构数据框为[(ID,"double"),("LOG_IN_DATE","date"),(USER,"string")]
,我想在Scala 2.11的Spark 2.0.2中应用上面的Dataframe。
我已经尝试过:
schema.map(x => df.withColumn(x._1, col(x._1).cast(x._2)))
运行此命令时没有错误,但之后当我调用df.schema时,没有任何更改。
有关如何以编程方式将架构应用于df的任何想法?我的朋友告诉我,我可以使用foldLeft
方法,但我不认为这是Spark 2.0.2中的方法,无论是df还是rdd。
答案 0 :(得分:6)
如果您已有列表[(ID,"double"),("LOG_IN_DATE","date"),(USER,"string")]
,则可以使用选择将每列投射到列表中的类型
您的数据框
val df = Seq(("1", "2017-11-01", "Johns"), ("2", "2018-01-03", "jons2")).toDF("ID", "LOG_IN_DATE", "USER")
您的架构
val schema = List(("ID", "double"), ("LOG_IN_DATE", "date"), ("USER", "string"))
从列表
中将所有列投射到其类型val newColumns = schema.map(c => col(c._1).cast(c._2))
选择所有te terted列
val newDF = df.select(newColumns:_*)
打印架构
newDF.printSchema()
root
|-- ID: double (nullable = true)
|-- LOG_IN_DATE: date (nullable = true)
|-- USER: string (nullable = true)
显示数据框
newDF.show()
输出:
+---+-----------+-----+
|ID |LOG_IN_DATE|USER |
+---+-----------+-----+
|1.0|2017-11-01 |Johns|
|2.0|2018-01-03 |Jons2|
+---+-----------+-----+
答案 1 :(得分:1)
我的朋友告诉我,我可以使用foldLeft方法,但我不认为这是Spark 2.0.2中的一种方法,无论是df还是rdd
是的,foldLeft
是要走的路
在使用schema
foldLeft
root
|-- ID: string (nullable = true)
|-- LOG_IN_DATE: string (nullable = true)
|-- USER: string (nullable = true)
使用foldLeft
val schema = List(("ID","double"),("LOG_IN_DATE","date"),("USER","string"))
import org.apache.spark.sql.functions._
schema.foldLeft(df){case(tempdf, x)=> tempdf.withColumn(x._1, col(x._1).cast(x._2))}.printSchema()
这是schema
foldLeft
root
|-- ID: double (nullable = true)
|-- LOG_IN_DATE: date (nullable = true)
|-- USER: string (nullable = true)
我希望答案很有帮助
答案 2 :(得分:0)
如果应用Scala的任何功能,它将返回已修改的数据,因此您无法更改现有架构的数据类型。
下面是通过转换列来创建修改模式的新数据框的代码。
1.创建一个新的DataFrame
val df=Seq((1,"2017-11-01","Johns"),(2,"2018-01-03","Alice")).toDF("ID","LOG_IN_DATE","USER")
2.将DataFrame注册为临时表
df.registerTempTable("user")
3.现在通过转换列数据类型
来创建新的DataFrameval new_df=spark.sql("""SELECT ID,TO_DATE(CAST(UNIX_TIMESTAMP(LOG_IN_DATE, 'yyyy-MM-dd') AS TIMESTAMP)) AS LOG_IN_DATE,USER from user""")
4。显示架构
new_df.printSchema
root
|-- ID: integer (nullable = false)
|-- LOG_IN_DATE: date (nullable = true)
|-- USER: string (nullable = true)
答案 3 :(得分:0)
其实你做了什么:
schema.map(x => df.withColumn(x._1, col(x._1).cast(x._2)))
可行,但您需要将数据框定义为 var 并执行以下操作:
for((name, type) <- schema) {
df = df.withColumn(name, col(name).cast(type)))
}
您也可以尝试阅读这样的数据框:
case class MyClass(ID: Int, LOG_IN_DATE: Date, USER: String)
//Suppose you are reading from json
val df = spark.read.json(path).as[MyClass]
希望这有帮助!