我有两个表,一个名为Reasons,有9条记录,另一个包含ID为40k的记录。
ID:
+------+------+
|pc_pid|pc_aid|
+------+------+
| 4569| 1101|
| 63961| 1101|
|140677| 4364|
|127113| 7|
| 96097| 480|
| 8309| 3129|
| 45218| 89|
|147036| 3289|
| 88493| 3669|
| 29973| 3129|
|127444| 3129|
| 36095| 89|
|131001| 1634|
|104731| 781|
| 79219| 244|
+-------------+
原因:
+-----------------+
| reasons|
+-----------------+
| follow up|
| skin chk|
| annual meet|
|review lab result|
| REF BY DR|
| sick visit|
| body pain|
| test|
| other|
+-----------------+
我想要这样的输出
|pc_pid|pc_aid| reason
+------+------+-------------------
| 4569| 1101| body pain
| 63961| 1101| review lab result
|140677| 4364| body pain
|127113| 7| sick visit
| 96097| 480| test
| 8309| 3129| other
| 45218| 89| follow up
|147036| 3289| annual meet
| 88493| 3669| review lab result
| 29973| 3129| REF BY DR
|127444| 3129| skin chk
| 36095| 89| other
由于我只有9条记录的原因,在ID数据框中我有40k条记录,我想随机为每个ID分配原因。
答案 0 :(得分:2)
以下解决方案尝试对原因的数量更加健壮(即,您可以拥有尽可能多的理由适合您的群集)。如果你只有几个理由(比如OP问),你可以广播它们或将它们嵌入 udf 中并轻松解决这个问题。
一般的想法是出于原因创建索引(顺序),然后在ID数据集上创建从0到N(其中N是原因数)的随机值,然后使用这两个新列连接两个表。以下是如何做到这一点:
case class Reasons(s: String)
defined class Reasons
case class Data(id: Long)
defined class Data
数据将保存ID(OP的简化版本),原因将包含一些简化的原因。
val d1 = spark.createDataFrame( Data(1) :: Data(2) :: Data(10) :: Nil)
d1: org.apache.spark.sql.DataFrame = [id: bigint]
d1.show()
+---+
| id|
+---+
| 1|
| 2|
| 10|
+---+
val d2 = spark.createDataFrame( Reasons("a") :: Reasons("b") :: Reasons("c") :: Nil)
+---+
| s|
+---+
| a|
| b|
| c|
+---+
我们稍后会需要多少理由,所以我们先计算一下。
val numerOfReasons = d2.count()
val d2Indexed = spark.createDataFrame(d2.rdd.map(_.getString(0)).zipWithIndex)
d2Indexed.show()
+---+---+
| _1| _2|
+---+---+
| a| 0|
| b| 1|
| c| 2|
+---+---+
val d1WithRand = d1.select($"id", (rand * numerOfReasons).cast("int").as("rnd"))
最后一步是加入新列并删除它们。
val res = d1WithRand.join(d2Indexed, d1WithRand("rnd") === d2Indexed("_2")).drop("_2").drop("rnd")
res.show()
+---+---+
| id| _1|
+---+---+
| 2| a|
| 10| b|
| 1| c|
+---+---+
答案 1 :(得分:0)
pyspark随机加入自己
data_neg = data_pos.sortBy(lambda x: uniform(1, 10000))
data_neg = data_neg.coalesce(1, False).zip(data_pos.coalesce(1, True))
答案 2 :(得分:0)
随机连接dataA(大数据框)和dataB(较小的数据框,按任意列排序)的最快方法:
dfB = dataB.withColumn(
"index", F.row_number().over(Window.orderBy("col")) - 1
)
dfA = dataA.withColumn("index", (F.rand() * dfB.count()).cast("bigint"))
df = dfA.join(dfB, on="index", how="left").drop("index")
由于 dataB 已经排序,因此可以在排序窗口上以高度并行的方式分配行号。 F.rand() 是另一个高度并行的函数,因此向 dataA 添加索引也会非常快。
如果 dataB 足够小,您可能会从广播中受益。
这种方法比使用更好:
参考:https://towardsdatascience.com/adding-sequential-ids-to-a-spark-dataframe-fa0df5566ff6