scala - 水平展开或旋转 spark scala 数据框以创建大型平面数据框
问题描述
我有一个具有以下架构的数据框:
UserID | StartDate | endDate | orderId | OrderCost| OrderItems| OrderLocation| Rank
1 到 10在哪里Rank
。我需要将此数据帧转置为等级并以以下格式创建数据帧:
UserID| StartDate_1 | endDate_1 | orderId_1 | OrderCost_1| OrderItems_1| OrderLocation_1|start_2 |endDate_2| orderId_2 | OrderCost_2| OrderItems_2| OrderLocation_2 |............| startDate_N|endDate_N | orderId_N | OrderCost_N| OrderItems_N| OrderLocation_N
如果用户只有两条排名为 3 和 10 的记录,则要求使用后缀填充列,_3
并且_10
该用户的其余单元格值将为空。
我尝试了 2 种蛮力方法
过滤 DF 以获取排名,并使用后缀重命名列并执行自连接回 DF。
按 UserID 分组,收集为列表并将其传递给 map 函数,在该函数中我根据排名填充数组,然后返回字符串的 seq。通过传递所需的模式创建 DF
两者似乎都在工作(不确定它是否正确)但它们不是通用的,我可以重新用于我拥有的不同用例
解决方案
在这个例子中,我使用了https://github.com/bokeh/bokeh/blob/master/bokeh/sampledata/_data/auto-mpg.csv
默认情况下,Spark 将排名放在前面,因此列名称与您指定的名称“相反”,但这只需几个步骤即可完成。关键是exprs
应该动态创建,并且agg
需要将其拆分为头部和尾部(这就是为什么.agg(exprs(0), exprs.slice(1, exprs.length)
下面有)
scala> df2.columns
res39: Array[String] = Array(mpg, cyl, displ, hp, weight, accel, yr, origin, name, Rank)
// note here, you would use columns.slice with the indices for
// the columns you need, i.e. (1, 7)
val exprs = for (col <- df2.columns.slice(0, 8)) yield expr(s"first(${col}) as ${col}")
exprs: Array[org.apache.spark.sql.Column] = Array(first(mpg, false) AS `mpg`, first(cyl, false) AS `cyl`, first(displ, false) AS `displ`, first(hp, false) AS `hp`, first(weight, false) AS `weight`, first(accel, false) AS `accel`, first(yr, false) AS `yr`, first(origin, false) AS `origin`)
scala> val resultDF = df2.groupBy("name").pivot("Rank").agg(exprs(0), exprs.slice(1, exprs.length):_*)
scala> resultDF.columns
res40: Array[String] = Array(name, 1_mpg, 1_cyl, 1_displ, 1_hp, 1_weight, 1_accel, 1_yr, 1_origin, 2_mpg, 2_cyl, 2_displ, 2_hp, 2_weight, 2_accel, 2_yr, 2_origin, 3_mpg, 3_cyl, 3_displ, 3_hp, 3_weight, 3_accel, 3_yr, 3_origin, 4_mpg, 4_cyl, 4_displ, 4_hp, 4_weight, 4_accel, 4_yr, 4_origin, 5_mpg, 5_cyl, 5_displ, 5_hp, 5_weight, 5_accel, 5_yr, 5_origin, 6_mpg, 6_cyl, 6_displ, 6_hp, 6_weight, 6_accel, 6_yr, 6_origin, 7_mpg, 7_cyl, 7_displ, 7_hp, 7_weight, 7_accel, 7_yr, 7_origin, 8_mpg, 8_cyl, 8_displ, 8_hp, 8_weight, 8_accel, 8_yr, 8_origin, 9_mpg, 9_cyl, 9_displ, 9_hp, 9_weight, 9_accel, 9_yr, 9_origin, 10_mpg, 10_cyl, 10_displ, 10_hp, 10_weight, 10_accel, 10_yr, 10_origin)
推荐阅读
- angular - 在 HTML 模板中调用时,默认 TS/JS 数据类型的方法会触发检测更改吗?
- php - Laravel Cashier 在 heroku 上不发送 POST 请求正文
- amazon-web-services - 具有事件模式的 Terraform AWS Cloudwatch 规则不起作用
- excel - 使用 excel 公开服务 oData 或 Rest?
- git - 使用 git rev-list --oneline 时如何显示提交日期?
- python-3.x - 应用 lambda 函数迭代两列
- python - 如何查找列表中是否连续有2个相同值的元素?
- c# - 协方差、泛型、UserControl
- r - 如何根据代表数据的曲线的高度通过渐变对绘图上的数据进行着色?
- vue.js - 带有视图列表的聊天视图 Nativescript vue