sparkSQL将一列拆分成多列

背景

我们在ETL数据处理过程中,有时会遇到以下业务场景,需要将一列拆分成多列,比如将一个类型为Array的字段按元素拆分成多列,或者将类型为Map的字段按value值拆分成多列,key值为每列的列名。假设某个大学教务系统,在学期末需要将学生的多科考试成绩录入系统,起初成绩是以Array类型存储[见下图],为了便于查询统计各科成绩的各项指标,需要将Array形式的成绩列拆分成多列。
在这里插入图片描述

方案一

适用于Array列是静态数据,大小固定有限

spark.createDataset(Seq(("201314001", Seq(90,91,95)),("201314002", Seq(89,96,92)))).toDF("id", "scores").selectExpr("id", "scores[0] as `高数`", "scores[1] as `线代`", "scores[2] as `Java编程`").show

方案二

适用于Array列是动态数据,且数组大小较大,调用Row.fromSeq方法将数组Array类型转换成Row类型,实现多列拆分。下面针对不同类型的原始数据使用不同的拆分办法。

  1. 原始数据是RDD类型
import org.apache.spark.sql.types._
import org.apache.spark.sql.Row
val newRDD = spark.createDataset(Seq(("201314001", Seq(90,91,95)),("201314002", Seq(89,96,92)))).rdd.map(ele => Row.fromSeq(ele._1+:ele._2))
val newSchema = StructType(StructField("id", StringType)+:Seq("高数","线代","Java编程").map(name => StructField(s"$name", IntegerType)))
spark.createDataFrame(newRDD, newSchema).show
  1. 原始数据是Dataset类型(含DataFrame,参见DataFrame转Dataset方式
import org.apache.spark.sql.types._
import org.apache.spark.sql.Row
import org.apache.spark.sql.catalyst.encoders.RowEncoder
val newSchema = StructType(StructField("id", StringType)+:Seq("高数","线代","Java编程").map(name => StructField(s"$name", DoubleType)))
spark.createDataset(Seq(("201314001", Seq(90,91,95)),("201314002", Seq(89,96,92)))).as[(String, Seq[Double])].map(ele => Row.fromSeq(ele._1+:ele._2))(RowEncoder(newSchema)).show

方案三

上述两方案是针对Array类型字段拆分成多列的有效方式,该方案针对Map类型字段做拆分。假设学生的成绩起初存储方式为Map类型,key值是各科名称,value值是各科成绩,见下图。
在这里插入图片描述

val curriculum = Seq("高数", "线代", "Java编程", "其它")
spark.createDataset(Seq(("201314001", Map("高数"->90, "线代"->91, "Java编程"->95)),("201314002", Map("高数"->89, "线代"->96, "Java编程"->92)))).toDF("id", "scores").selectExpr("id"+:curriculum.map(course=>s"scores['$course'] as `$course`"):_*).show

结果展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值