加入PySpark会产生意想不到的结果

时间:2016-11-02 21:40:20

标签: python join apache-spark pyspark

我使用Spark版本2.0.0和python版本3.5。我有一个包含两列的父表:GroupID和ID。我需要将数据分成3个子集,所以我使用分层抽样。

一旦我获得了我的子集(样本A),我执行左连接并查找样本A ID为空。预期输出是父表的子集,其不包含来自样本A的任何ID。

 [2,1 => ['expires' => true]] //array value 3 is removed 

在版本1中,将填充BC表,但会复制父表中的值。

spark = SparkSession.builder.enableHiveSupport().appName("myApp").getOrCreate()

data = [(0, 100), (0, 101), (0, 102), (0, 103), (0, 1000), (1, 104), (1,105), (1, 106), (1, 107), (1, 1007)]
df = spark.createDataFrame(data, ['group', 'id'])

## Stratified Sampling
fractions = dict((int(item), 0.45) for item in np.arange(0,(2)))
sampled_for_A = df.sampleBy("group", fractions, seed=7)
sampled_for_A.orderBy("id").show()

## Version 1

sampled_for_BC = df.join(sampled_for_A, df.id == sampled_for_A.id, "left_outer").select(df.group, df.id, sampled_for_A.group.alias("groupA"), sampled_for_A.id.alias("id_A"))
sampled_for_BC.where(sampled_for_BC.id_A.isNull()).show()

版本2 createOrReplaceTempView并使用sql查询执行LEFT JOIN返回预期结果

Group A
+-----+----+
|group|  id|
+-----+----+
|    0| 101|
|    0| 102|
|    1| 104|
|    1| 105|
|    1| 107|
|    0|1000|
+-----+----+

BC
+-----+----+------+----+
|group|  id|groupA|id_A|
+-----+----+------+----+
|    1| 107|     1| 107|
|    0| 103|     0| 103|
|    1| 104|     1| 104|
|    0|1000|     0|1000|
|    1| 106|     1| 106|
|    0| 100|     0| 100|
|    1| 105|     1| 105|
|    1|1007|     1|1007|
|    0| 101|     0| 101|
|    0| 102|     0| 102|
+-----+----+------+----+

正如所料:

df.createOrReplaceTempView("parentTable")
sampled_for_A.createOrReplaceTempView("groupA")

subset_BC = spark.sql(''' 
SELECT a.group,
   a.id,
   b.group AS group_A,
   b.id AS id_A
FROM parentTable a
LEFT JOIN groupA b
ON a.id = b.id
WHERE b.id IS NULL
''').show()

我缺少的版本1中的where子句是什么? (此外,我的数据有1亿行,甚至在版本2中执行的sql左连接也会表现得很奇怪。我还尝试在组列上重新分区。)非常感谢任何见解。

1 个答案:

答案 0 :(得分:0)

版本1中的id正常,但下一个选择会覆盖已加入的数据。这是因为groupdf列来自同一个数据框(df.group == sampled_for_A.group),所以基本上是>>> sampled_for_A_aliased = sampled_for_A \ ... .select(sampled_for_A.id.alias('id_A'), sampled_for_A.group.alias('groupA')) >>> df.join(sampled_for_A_aliased, df.id == sampled_for_A_aliased.id_A, "left_outer").show() +-----+----+----+------+ |group| id|id_A|groupA| +-----+----+----+------+ | 1| 107|null| null| | 0| 103|null| null| | 1| 104| 104| 1| | 0|1000|1000| 0| | 1| 106| 106| 1| | 0| 100|null| null| | 1| 105| 105| 1| | 1|1007|null| null| | 0| 101| 101| 0| | 0| 102| 102| 0| +-----+----+----+------+

要实现想要的行为,您必须在加入之前对列进行别名,例如:

{{1}}