如何在spark中对数据集的窗口进行子采样?

wz1wpwve  于 2021-05-19  发布在  Spark
关注(0)|答案(1)|浏览(509)

假设我有一个 DataSet 看起来是这样的:

  1. Name | Grade
  2. ---------------
  3. Josh | 94
  4. Josh | 87
  5. Amanda | 96
  6. Karen | 78
  7. Amanda | 90
  8. Josh | 88

我想创建一个新的 DataSet 其中,每个名称有3行,其他行(如果有的话)是从相同名称的行中取样的(例如,karen将有3行相同的行)。
我如何做到这一点而不循环通过每个名字?

sauutmhj

sauutmhj1#

数据准备:

  1. val df = Seq(("Josh",94),("Josh",87),("Amanda",96),("Karen",78),("Amanda",90),("Josh",88)).toDF("Name","Grade")

仅当您的数据 skewed 为了一个 Name :添加一个随机数,并为每个随机数筛选前3个随机数 Name .

  1. val df2 = df.withColumn("random", round(rand()*10))
  2. import org.apache.spark.sql.expressions.Window
  3. val windowSpec = Window.partitionBy("Name").orderBy("random")
  4. val df3 = df2.withColumn("row_number",row_number.over(windowSpec))
  5. .filter($"row_number" <= 3)

现在,为每个 Name 重复3次,确保每个人至少有3条记录 Name . 最后取前3个值 explode ```
df4.groupBy("Name").agg(collect_list("Grade") as "grade_list")
.withColumn("temp_list", slice( flatten(array_repeat($"grade_list", 3)), 1,3))
.select($"Name",explode($"temp_list") as "Grade").show

  1. 笔记:
  2. 因为上面的代码中最多有3个值 `grade_list` 因此,复制3次不会有什么害处。
  3. 如果你不使用 `Window` 步骤,你可以有一个组合 `when( size($"grade_list") === n, ).otherwise()` 避免不必要的重复。
展开查看全部

相关问题