Scala 如何使用映射对象列表创建Spark SQL数据框
我在Scala列表中有多个Map[String,String]。例如:Scala 如何使用映射对象列表创建Spark SQL数据框,scala,apache-spark,dataframe,apache-spark-sql,bigdata,Scala,Apache Spark,Dataframe,Apache Spark Sql,Bigdata,我在Scala列表中有多个Map[String,String]。例如: map1 = Map("EMP_NAME" -> “Ahmad”, "DOB" -> “01-10-1991”, "CITY" -> “Dubai”) map2 = Map("EMP_NAME" -> “Rahul”, "DOB" -> “06-12-1991”, "CITY" -> “Mumbai”) map3 = Map("EMP_NAME" -> “John”, "DOB" -
map1 = Map("EMP_NAME" -> “Ahmad”, "DOB" -> “01-10-1991”, "CITY" -> “Dubai”)
map2 = Map("EMP_NAME" -> “Rahul”, "DOB" -> “06-12-1991”, "CITY" -> “Mumbai”)
map3 = Map("EMP_NAME" -> “John”, "DOB" -> “11-04-1996”, "CITY" -> “Toronto”)
list = List(map1, map2, map3)
现在我想创建一个数据帧,如下所示:
EMP_NAME DOB CITY
Ahmad 01-10-1991 Dubai
Rahul 06-12-1991 Mumbai
John 11-04-1996 Toronto
我如何做到这一点?您可以这样做:
import spark.implicits._
val df = list
.map( m => (m.get("EMP_NAME"),m.get("DOB"),m.get("CITY")))
.toDF("EMP_NAME","DOB","CITY")
df.show()
+--------+----------+-------+
|EMP_NAME| DOB| CITY|
+--------+----------+-------+
| Ahmad|01-10-1991| Dubai|
| Rahul|06-12-1991| Mumbai|
| John|11-04-1996|Toronto|
+--------+----------+-------+
您可以这样做:
import spark.implicits._
val df = list
.map( m => (m.get("EMP_NAME"),m.get("DOB"),m.get("CITY")))
.toDF("EMP_NAME","DOB","CITY")
df.show()
+--------+----------+-------+
|EMP_NAME| DOB| CITY|
+--------+----------+-------+
| Ahmad|01-10-1991| Dubai|
| Rahul|06-12-1991| Mumbai|
| John|11-04-1996|Toronto|
+--------+----------+-------+
稍微不太具体的方法,例如:
val map1 = Map("EMP_NAME" -> "Ahmad", "DOB" -> "01-10-1991", "CITY" -> "Dubai")
val map2 = Map("EMP_NAME" -> "John", "DOB" -> "01-10-1992", "CITY" -> "Mumbai")
///...
val list = List(map1, map2) // map3, ...
val RDDmap = sc.parallelize(list)
// Get cols dynamically
val cols = RDDmap.take(1).flatMap(x=> x.keys)
// Map is K,V like per Map entry
val df = RDDmap.map{ value=>
val list=value.values.toList
(list(0), list(1), list(2))
}.toDF(cols:_*) // dynamic column names assigned
df.show(false)
返回:
+--------+----------+------+
|EMP_NAME|DOB |CITY |
+--------+----------+------+
|Ahmad |01-10-1991|Dubai |
|John |01-10-1992|Mumbai|
+--------+----------+------+
或者回答你的子问题,如下所示——至少我认为这是你要问的,但可能不是:
val RDDmap = sc.parallelize(List(
Map("EMP_NAME" -> "Ahmad", "DOB" -> "01-10-1991", "CITY" -> "Dubai"),
Map("EMP_NAME" -> "John", "DOB" -> "01-10-1992", "CITY" -> "Mumbai")))
...
// Get cols dynamically
val cols = RDDmap.take(1).flatMap(x=> x.keys)
// Map is K,V like per Map entry
val df = RDDmap.map{ value=>
val list=value.values.toList
(list(0), list(1), list(2))
}.toDF(cols:_*) // dynamic column names assigned
当然,您可以动态地构建一个列表,但仍然需要分配贴图元素。看见我只要从文件中读出来就可以了 稍微不太具体的方法,例如:
val map1 = Map("EMP_NAME" -> "Ahmad", "DOB" -> "01-10-1991", "CITY" -> "Dubai")
val map2 = Map("EMP_NAME" -> "John", "DOB" -> "01-10-1992", "CITY" -> "Mumbai")
///...
val list = List(map1, map2) // map3, ...
val RDDmap = sc.parallelize(list)
// Get cols dynamically
val cols = RDDmap.take(1).flatMap(x=> x.keys)
// Map is K,V like per Map entry
val df = RDDmap.map{ value=>
val list=value.values.toList
(list(0), list(1), list(2))
}.toDF(cols:_*) // dynamic column names assigned
df.show(false)
import org.apache.spark.SparkContext
import org.apache.spark.sql._
import org.apache.spark.sql.types.{StringType, StructField, StructType}
object DataFrameTest2 extends Serializable {
var sparkSession: SparkSession = _
var sparkContext: SparkContext = _
var sqlContext: SQLContext = _
def main(args: Array[String]): Unit = {
sparkSession = SparkSession.builder().appName("TestMaster").master("local").getOrCreate()
sparkContext = sparkSession.sparkContext
val sqlContext = new org.apache.spark.sql.SQLContext(sparkContext)
val map1 = Map("EMP_NAME" -> "Ahmad", "DOB" -> "01-10-1991", "CITY" -> "Dubai")
val map2 = Map("EMP_NAME" -> "Rahul", "DOB" -> "06-12-1991", "CITY" -> "Mumbai")
val map3 = Map("EMP_NAME" -> "John", "DOB" -> "11-04-1996", "CITY" -> "Toronto")
val list = List(map1, map2, map3)
//create your rows
val rows = list.map(m => Row(m.values.toSeq:_*))
//create the schema from the header
val header = list.head.keys.toList
val schema = StructType(header.map(fieldName => StructField(fieldName, StringType, true)))
//create your rdd
val rdd = sparkContext.parallelize(rows)
//create your dataframe using rdd
val df = sparkSession.createDataFrame(rdd, schema)
df.show()
}
}
返回:
+--------+----------+------+
|EMP_NAME|DOB |CITY |
+--------+----------+------+
|Ahmad |01-10-1991|Dubai |
|John |01-10-1992|Mumbai|
+--------+----------+------+
或者回答你的子问题,如下所示——至少我认为这是你要问的,但可能不是:
val RDDmap = sc.parallelize(List(
Map("EMP_NAME" -> "Ahmad", "DOB" -> "01-10-1991", "CITY" -> "Dubai"),
Map("EMP_NAME" -> "John", "DOB" -> "01-10-1992", "CITY" -> "Mumbai")))
...
// Get cols dynamically
val cols = RDDmap.take(1).flatMap(x=> x.keys)
// Map is K,V like per Map entry
val df = RDDmap.map{ value=>
val list=value.values.toList
(list(0), list(1), list(2))
}.toDF(cols:_*) // dynamic column names assigned
当然,您可以动态地构建一个列表,但仍然需要分配贴图元素。看见我只要从文件中读出来就可以了 谢谢。还有一点:如何动态循环这个列表0,列表1,列表2?我的意思是,与其硬编码1、2和3,它可以从类似listi的东西中获取吗?更新的答案实际上是另一个答案。请接受其他情况。@BluePhantom,我不会假设映射的.key和.value的结果将始终保持KV成对顺序。@LeoC请详细说明如果m=Map1->a,2->b,…,我认为假设m.key和m.value的元素一定会像1,2。。。和a,b,…,因为映射和集合都不保持顺序。谢谢你。还有一点:如何动态循环这个列表0,列表1,列表2?我的意思是,与其硬编码1、2和3,它可以从类似listi的东西中获取吗?更新的答案实际上是另一个答案。请接受其他情况。@BluePhantom,我不会假设映射的.key和.value的结果将始终保持KV成对顺序。@LeoC请详细说明如果m=Map1->a,2->b,…,我认为假设m.key和m.value的元素一定会像1,2。。。和a,b,…,因为Map和Set都不保留顺序。协议是您选择其他答案中的一个作为正确答案,除非没有其他人提供或您认为它们不合适。我认为在这种情况下,所有答案都是正确的。你的也是第一个。不确定如何标记多个正确答案。另外,我只是在寻找最通用的解决方案。在real中,我将为大约40多个列动态创建和填充数据集。顺便说一句,我非常感谢您提供的解决方案:那么请接受它,因为它更灵活,对于40 cols方法,。但你可以投票。选择权在你。我多次高估了你的答案。但我得到的信息是:谢谢你的反馈!声誉低于15的人所投的票将被记录,但不会改变公开显示的帖子分数:看来我需要先建立自己的声誉:对,就是这样。然后,你可以只接受答案,如果你认为这是最好的,那么就这样做,否则就选择另一个。协议是你选择其他答案中的一个作为正确答案,除非没有其他人提供,或者你觉得它们不合适。我认为在这种情况下,所有答案都是正确的。你的也是第一个。不确定如何标记多个正确答案。另外,我只是在寻找最通用的解决方案。在real中,我将为大约40多个列动态创建和填充数据集。顺便说一句,我非常感谢您提供的解决方案:那么请接受它,因为它更灵活,对于40 cols方法,。但你可以投票。选择权在你。我多次高估了你的答案。但我得到的信息是:谢谢你的反馈!声誉低于15的人所投的票将被记录,但不会改变公开显示的帖子分数:看来我需要先建立自己的声誉:对,就是这样。然后你只能接受答案,如果你认为它是最好的,那么就这样做,否则就选择另一个。
import org.apache.spark.SparkContext
import org.apache.spark.sql._
import org.apache.spark.sql.types.{StringType, StructField, StructType}
object DataFrameTest2 extends Serializable {
var sparkSession: SparkSession = _
var sparkContext: SparkContext = _
var sqlContext: SQLContext = _
def main(args: Array[String]): Unit = {
sparkSession = SparkSession.builder().appName("TestMaster").master("local").getOrCreate()
sparkContext = sparkSession.sparkContext
val sqlContext = new org.apache.spark.sql.SQLContext(sparkContext)
val map1 = Map("EMP_NAME" -> "Ahmad", "DOB" -> "01-10-1991", "CITY" -> "Dubai")
val map2 = Map("EMP_NAME" -> "Rahul", "DOB" -> "06-12-1991", "CITY" -> "Mumbai")
val map3 = Map("EMP_NAME" -> "John", "DOB" -> "11-04-1996", "CITY" -> "Toronto")
val list = List(map1, map2, map3)
//create your rows
val rows = list.map(m => Row(m.values.toSeq:_*))
//create the schema from the header
val header = list.head.keys.toList
val schema = StructType(header.map(fieldName => StructField(fieldName, StringType, true)))
//create your rdd
val rdd = sparkContext.parallelize(rows)
//create your dataframe using rdd
val df = sparkSession.createDataFrame(rdd, schema)
df.show()
}
}