行列之间的互相转换是ETL中的常见需求,在Spark SQL中,行转列有内建的PIVOT函数可用,没什么特别之处。而列转行要稍微麻烦点。本文整理了2种可行的列转行方法,供参考。

本文链接:https://www.cnblogs.com/hhelibeb/p/10310369.html

测试数据准备

本文的环境是Windows 10, Spark 2.4,开发语言是Python。首先构建一点初始测试数据,

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName('TestAPP').enableHiveSupport().getOrCreate()

df = spark.createDataFrame([('数学','张三',88), ('语文','张三',92), ('英语','张三',77),
('数学','王五',65), ('语文','王五',87), ('英语','王五',90),
('数学','李雷',67), ('语文','李雷',33), ('英语','李雷',24),
('数学','宫九',77), ('语文','宫九',87), ('英语','宫九',90)
], ['科目','姓名','分数']).orderBy('科目') df.show()

执行程序,可以看到数据如下,

    +----+----+----+
|科目|姓名|分数|
+----+----+----+
|数学|张三| 88|
|数学|李雷| 67|
|数学|宫九| 77|
|数学|王五| 65|
|英语|张三| 77|
|英语|宫九| 90|
|英语|李雷| 24|
|英语|王五| 90|
|语文|李雷| 33|
|语文|宫九| 87|
|语文|张三| 92|
|语文|王五| 87|
+----+----+----+

行转列

如上述,使用PIVOT函数即可实现行转列,

df.createOrReplaceTempView('scores')

sql_content = '''select * from scores
pivot
(
sum(`分数`) for
`姓名` in ('张三','王五','李雷','宫九')
)
''' df_pivot = spark.sql(sql_content)
df_pivot.show()

得到结果,

+----+----+----+----+----+
|科目|张三|王五|李雷|宫九|
+----+----+----+----+----+
|数学| 88| 65| 67| 77|
|英语| 77| 90| 24| 90|
|语文| 92| 87| 33| 87|
+----+----+----+----+----+

列转行

本文整理的两种办法是使用Spark中的stack函数lateral view + explode函数

stack()

stack(n, expr1, ..., exprk) - 会将expr1, ..., exprk 分割为n行.

df_pivot.createOrReplaceTempView('v_pivot')

sql_content = '''select `科目`,
stack(4, '张三', `张三`, '王五', `王五`, '李雷', `李雷`, '宫九', `宫九`) as (`姓名`, `分数` )
from v_pivot
''' df_unpivot1 = spark.sql(sql_content) df_unpivot1.show()

可以看到,结果的结构和初始数据的结构相同,

+----+----+----+
|科目|姓名|分数|
+----+----+----+
|数学|张三| 88|
|数学|王五| 65|
|数学|李雷| 67|
|数学|宫九| 77|
|英语|张三| 77|
|英语|王五| 90|
|英语|李雷| 24|
|英语|宫九| 90|
|语文|张三| 92|
|语文|王五| 87|
|语文|李雷| 33|
|语文|宫九| 87|
+----+----+----+

lateral view + explode()

explode函数可以把数组分割为多行,比如,

> SELECT explode(array(10, 20));
10
20

lateral view使用表生成函数将每个输入行转换为0或多个输出行。最常见的用法是和explode函数一起使用。

sql_content = '''select `科目`, split(temp1, ':')[0] as `姓名`, split(temp1, ':')[1] as `分数`
from(
select `科目`, concat(
'张三:', `张三`, ',',
'王五:', `王五`, ',',
'李雷:', `李雷`, ',',
'宫九:', `宫九`
) temp
from v_pivot
) lateral view explode(split(temp, ',')) as temp1
'''
df_unpivot2 = spark.sql(sql_content) df_unpivot2.show()

结果同上,

+----+----+----+
|科目|姓名|分数|
+----+----+----+
|数学|张三| 88|
|数学|王五| 65|
|数学|李雷| 67|
|数学|宫九| 77|
|英语|张三| 77|
|英语|王五| 90|
|英语|李雷| 24|
|英语|宫九| 90|
|语文|张三| 92|
|语文|王五| 87|
|语文|李雷| 33|
|语文|宫九| 87|
+----+----+----+

参考链接:Spark SQL, Built-in Functions

Spark实现行列转换pivot和unpivot

hive lateral view 与 explode详解

SQL Guide

Spark SQL中列转行(UNPIVOT)的两种方法的更多相关文章

  1. .net中创建xml文件的两种方法

    .net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...

  2. 在Delphi中使用C++对象(两种方法,但都要改造C++提供的DLL)

    Delphi是市场上最好的RAD工具,但是现在C++占据着主导地位,有时针对一个问题很难找到Delphi或Pascal的解决方案.可是却可能找到了一个相关的C++类.本文描述几种在Delphi代码中使 ...

  3. Oracle中spool命令实现的两种方法比较

    ---恢复内容开始--- 要输出符合要求格式的数据文件只需在select时用字符连接来规范格式.比如有如下表 SQL>; select id,username,password from myu ...

  4. 在List中找出最大值的两种方法

    先说需求:找出一个对象List中,某个属性值最大的对象. 1.定义对象 private class A { public int ID { get; set; } public string Name ...

  5. 在shell script中进行数值运算的两种方法

    方法1:使用"$((计算式))"的方式进行数值运算,不需要使用declare命令显示声明数值型变量来存储计算结果: 方法2:使用declare命令配合"-i"选 ...

  6. Android中Intent传递对象的两种方法(Serializable,Parcelable)

    今天要给大家讲一下Android中 Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是 Bundle.putP ...

  7. Python 中格式化字符串 % 和 format 两种方法之间的区别

    Python2.6引入了 format 格式化字符串的方法,现在格式化字符串有两种方法,就是 % 和 format ,具体这两种方法有什么区别呢?请看以下解析. # 定义一个坐标值 c = (250, ...

  8. [转]Android中Intent传递对象的两种方法(Serializable,Parcelable)

    http://blog.csdn.net/xyz_lmn/article/details/5908355 今天要给大家讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种 ...

  9. Android高手进阶教程(十七)之---Android中Intent传递对象的两种方法(Serializable,Parcelable)!

    [转][原文] 大家好,好久不见,今天要给大家讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object); ...

随机推荐

  1. WARNING: 'aclocal-1.14' is missing on your system.

    源码安装zabbix agent时进行到make install时报如下错误: WARNING: 'aclocal-1.14' is missing on your system. You shoul ...

  2. .NET Core玩转机器学习

    最近在搞机器学习,目前国内没有什么关于ML.NET的教程,官方都是一大堆英文,经过了我的努力,找到了Relax Development大哥的博客,有关于ML.NET的内容 原文地址:https://w ...

  3. SpringBoot入门教程(六)SpringBoot2.0统一处理404,500等http错误跳转页

    在做web项目的时候,大家对404.500等http状态码肯定并不陌生.然而无论是哪种"非正常"状态码,都不是我们想遇到的.尤其像一些500这种服务器内部错误,不愿意展示给用户的, ...

  4. ES6躬行记(16)——Set

    ES6引入了两种新的数据结构:Set和Map.Set是一组值的集合,其中值不能重复:Map(也叫字典)是一组键值对的集合,其中键不能重复.Set和Map都由哈希表(Hash Table)实现,并可按添 ...

  5. 在.NET Core中使用简单的插件化机制

    前言 插件化,其实也并不是什么新东西了,像nopCommerce等开源项目都有类似的机制,而且功能比较完善和齐全. 相信大家都对接过不少支付方式,支付宝.微信以及各大银行或第三方的支付公司. 我们可以 ...

  6. #8 Python网络编程(一)

    前言 语言是用来交流的,人类语言使人与人交流,编程语言使人与机器交流,那么问题来了,机器如何与机器交流.你是否疑惑过:为什么我们可以使用浏览器查资料.为什么我们可以使用聊天软件聊天.为什么我们可以通过 ...

  7. Spring Cloud Alibaba与Spring Boot、Spring Cloud之间不得不说的版本关系

    这篇博文是临时增加出来的内容,主要是由于最近连载<Spring Cloud Alibaba基础教程>系列的时候,碰到读者咨询的大量问题中存在一个比较普遍的问题:版本的选择.其实这类问题,在 ...

  8. 服务器控件的几个属性 SelectedIndex、SelectedItem、SelectedValue、SelectedItem.Text、selectedItem.value

    转自http://blog.csdn.net/iqv520/article/details/4419186 1. SelectedIndex ——选项的索引,为int,从0开始,可读可写 2. Sel ...

  9. 拯救老旧工程,记桥接SpringMVC与Stripes框架

    背景: 公司基础设施部门推出了自己的微服务框架(以下简称M),要求所有业务应用都要接入进去,但坑爹的是M只提供了SpringMVC工程的support,对于采用Stripes作为MVC框架的应用并不支 ...

  10. js 颜色16进制转RGB方法

    //颜色16进制转RGB方法 String.prototype.colorRgb = function(){ var sColor = this.toLowerCase(); //十六进制颜色值的正则 ...