我有一个这样的Spark数据框:
+-----+-----+-------+--------+
| A |B |2017Q1 | 2017Q2 |
+-----+----------------------+
| 1 | 101| 0.6 | 0.8 |
| 2 | 102| 0.7 | 0.9 |
| 3 | 103| 0.9 | 0.4 |
| ...| ...| ... | ... |
此处的年和季度列可以是动态的。
意味着我也可能会获得2017Q3、2017Q4等的专栏。
我想将2017Q1
和2017Q2
的列值转换为行,如下所示:
+-----+-----+-------+--------+----+
| A |B |Year | Quarter|Val |
+-----+----------------------+----+
| 1 | 101| 2017 | 1 |0.6 |
| 1 | 101| 2017 | 2 |0.8 |
| 2 | 102| 2017 | 1 |0.7 |
| ...| ...| ... | ... |. |
有人可以帮我这个忙吗?我正在使用Spark 2.4.4
答案 0 :(得分:2)
在Spark SQL中,您可以创建一个包含两个季度值的数组。由于您需要记住哪个值对应于哪个四分之一,因此可以创建一个结构以将四分之一的索引与其值绑定。要使其动态,可以使用四分之一的列表。为了使其更加通用,我们可以按如下所示从数据框的列名称中提取四分之一。
val quarters = df.columns
.filter( _.matches("[0-9]{4}Q[1-4]") ) // all the columns matching the regex
.sorted
df.withColumn("value", explode(array(
quarters.indices.map(i =>
struct(lit(i+1) as "val", col(quarters(i)) as "quarter")
) : _*
)))
.withColumn("Quarter", $"value.quarter")
.withColumn("Val", $"value.val")
.drop( quarters :+ "value" : _*)