Spark SQL中如何将多列拆分为多行并保留列名信息
嗨,我来帮你搞定这个需求!你需要把col3、col4、col5这几列拆成单行,同时保留对应的列名作为col_num,Spark 2.2.0有两种很实用的方法可以实现:
方法1:用struct+array+explode组合
这个方法先把每个目标列的列名和对应值打包成结构体,再放到数组里,最后展开数组提取字段:
import org.apache.spark.sql.functions.{array, col, explode, lit, struct} // 假设你的原始DataFrame名为df val transformedDF = df.select( col("col1"), col("col2"), array( struct(lit("col3").as("col_num"), col("col3").as("col_new")), struct(lit("col4").as("col_num"), col("col4").as("col_new")), struct(lit("col5").as("col_num"), col("col5").as("col_new")) ).as("cols_array") ) val resultDF = transformedDF .withColumn("cols", explode(col("cols_array"))) .select( col("col1"), col("col2"), col("cols.col_num"), col("cols.col_new") ) resultDF.show()
方法2:用stack函数(更简洁)
Spark 2.2.0支持stack函数,它可以直接把多列转成键值对形式,一步到位:
import org.apache.spark.sql.functions.stack val resultDF = df.select( col("col1"), col("col2"), stack(3, // 要转换的列的数量 "col3", col("col3"), "col4", col("col4"), "col5", col("col5") ).as(Seq("col_num", "col_new")) // 给转换后的两列命名 ) resultDF.show()
为什么你的之前尝试没得到col_num?
你之前用array+explode只把列的值放进了数组,没有把列名和值绑定在一起,所以展开后丢失了列名信息。上面两种方法都把列名(用lit生成固定字符串或者直接在stack里传入)和对应值关联起来,这样就能同时保留你需要的col_num和col_new了。
内容的提问来源于stack exchange,提问作者alex-arkhipov
相关产品推荐
相关产品推荐

