我有一个从JSON对象创建的数据帧。我可以查询这个数据帧并将其写入实木复合地板。
由于我推断出架构,我不一定知道数据帧中有什么。
有没有办法将列名称输出或使用自己的模式映射数据框?
var a = {"name":"ab\
ac", age:"112"};
我想做点什么
// The results of SQL queries are DataFrames and support all the normal RDD operations.
// The columns of a row in the result can be accessed by field index:
df.map(t => "Name: " + t(0)).collect().foreach(println)
// or by field name:
df.map(t => "Name: " + t.getAs[String]("name")).collect().foreach(println)
// row.getValuesMap[T] retrieves multiple columns at once into a Map[String, T]
df.map(_.getValuesMap[Any](List("name", "age"))).collect().foreach(println)
// Map("name" -> "Justin", "age" -> 19)
不知道列的实际数量或名称。
答案 0 :(得分:4)
嗯,你可以但结果却毫无用处:
val df = Seq(("Justin", 19, "red")).toDF("name", "age", "color")
def getValues(row: Row, names: Seq[String]) = names.map(
name => name -> row.getAs[Any](name)
).toMap
val names = df.columns
df.rdd.map(getValues(_, names)).first
// scala.collection.immutable.Map[String,Any] =
// Map(name -> Justin, age -> 19, color -> red)
为了获得实际有用的东西,可以在SQL类型和Scala类型之间进行正确的映射。在简单的情况下并不难,但总的来说很难。例如,内置类型可用于表示任意struct
。这可以通过一些元编程来完成,但可以说它不值得大惊小怪。
答案 1 :(得分:0)
您可以使用隐式编码器并在DataFrame本身上执行映射:
implicit class DataFrameEnhancer(df: DataFrame) extends Serializable {
implicit val encoder = RowEncoder(df.schema)
implicit def mapNameAndAge(): DataFrame = {
df.map(row => (row.getAs[String]("name") -> row.getAs[Int]("age")))
}
}
并按如下方式在您的数据框上调用它:
val df = Seq(("Justin", 19, "red")).toDF("name", "age", "color")
df.mapNameAndAge().first
那样,您不必将DataFrame转换为RDD(在某些情况下,您不想从磁盘上加载整个DF,只需加载某些列,但是RDD转换迫使您执行此操作另外,您使用编码器而不是Kryo(或其他Java SerDes),速度更快。
希望它会有所帮助:-)