【问题标题】:How to transform this dataset to the following dataset如何将此数据集转换为以下数据集
【发布时间】:2021-05-23 09:48:33
【问题描述】:

输入

+------+------+------+------+
|emp_name|emp_area| dept|zip| 
+------+------+------+------+
|ram|USA|"Sales"|805912|     
|sham|USA|"Sales"|805912|   
|ram|Canada|"Marketing"|805912|   
|ram|USA|"Sales"|805912|
|sham|USA|"Marketing"|805912|      
+------+------+------+------

期望的输出

feature   |Top1 name |Top 1 value1|Top2 name|top 2 value|

emp_name    ram |3|sham |2
emp_area    Usa |4|canada |1    
dept       sales|3|Marketing|3
zip         805912|5|NA|NA      

我开始为它们中的每一个动态生成计数,但无法将它们存储在数据集中

val features=ds.columns.toList
for (e <- features) {
  val ds1=ds.groupBy(e).count().sort(desc("count")).limit(5).withColumnRenamed("count", e+"_count")
}

现在如何将所有值收集到一个数据帧中并转换为输出?

【问题讨论】:

    标签: scala apache-spark apache-spark-sql apache-spark-dataset apache-spark-2.0


    【解决方案1】:

    这是一个稍微冗长的方法。您可以map 每一列到一个具有一行的数据框,该行对应于所需输出中的行。如有必要,添加 NA 列。将列名称转换为所需的名称,最后执行unionAll 以组合数据框(每行)。

    import org.apache.spark.sql.expressions.Window
    
    val top = 2
    
    val result = ds.columns.map(
        c => ds.groupBy(c).count()
               .withColumn("rn", row_number().over(Window.orderBy(desc("count"))))
               .filter(s"rn <= $top")
               .groupBy().pivot("rn")
               .agg(first(col(c)), first(col("count")))
               .select(lit(c), col("*"))
    ).map(df => 
        if (df.columns.size != 1 + top*2)
            df.select(List(col("*")) ::: (1 to (top*2+1 - df.columns.size)).toList.map(x => lit("NA")): _*)
        else df
    ).map(df =>
        df.toDF(List("feature") ::: (1 to top).toList.flatMap(x => Seq(s"top$x name", s"top$x value")): _*)
    ).reduce(_ unionAll _)
    
    result.show
    +--------+---------+----------+---------+----------+
    | feature|top1 name|top1 value|top2 name|top2 value|
    +--------+---------+----------+---------+----------+
    |emp_name|      ram|         3|     sham|         2|
    |emp_area|      USA|         4|   Canada|         1|
    |    dept|    Sales|         3|Marketing|         2|
    |     zip|   805912|         5|       NA|        NA|
    +--------+---------+----------+---------+----------+
    

    【讨论】:

    • 首先,我们循环每个列并应用枢轴和分组依据并选择列,您能解释一下地图中的代码吗?
    • 第二个地图添加了 NA 列,以确保所有数据帧具有相同的列数。第三个映射更改数据框的列名以匹配您所需的输出。
    猜你喜欢
    • 2015-11-28
    • 2016-11-01
    • 2012-02-17
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    相关资源
    最近更新 更多