如何比较两个数据帧并在pyspark中添加新的标志列?

时间:2018-02-09 11:32:02

标签: apache-spark pyspark apache-spark-sql spark-dataframe pyspark-sql

我通过执行以下命令创建了两个数据帧。

test1 = sc.parallelize([
    ("a",1,1),
    ("b",2,2),
    ("d",4,2),
    ("e",4,1),
    ("c",3,4)]).toDF(['SID','SSection','SRank'])
test1.show()
+---+--------+-----+
|SID|SSection|SRank|
+---+--------+-----+
|  a|       1|    1|
|  b|       2|    2|
|  d|       4|    2|
|  e|       4|    1|
|  c|       3|    4|
+---+--------+-----+

test2=sc.parallelize([
    ("a",1,1),
    ("b",2,3),
    ("f",4,2),
    ("e",4,1),
    ("c",3,4)]).toDF(['SID','SSection','SRank'])
test2.show()
+---+--------+-----+
|SID|SSection|SRank|
+---+--------+-----+
|  a|       1|    1|
|  b|       2|    3|
|  f|       4|    2|
|  e|       4|    1|
|  c|       3|    4|
+---+--------+-----+

使用test1和test2数据帧我需要生成新的数据帧,其中应包含如下所示的结果。

+---+--------+----------+------------+------------+
|SID|SSection|test1SRank|test2SRank  |      flag  |
+---+--------+----------+------------+------------+
|  a|       1|    1     |       1    | same_rank  |
|  b|       2|    2     |       3    |rank_changed|
|  d|       4|    2     |       0    |No_rank     |
|  e|       4|    1     |       1    |same_rank   |
|  c|       3|    4     |       4    |same_rank   |
|  f|       4|    0     |       2    |new_rank    |
+---+--------+----------+------------+------------+

以上结果我想通过使用SIDSSection列的组合以及ranks之间的比较来比较test1和test2数据框。

例如:

1)SID (a)和SSection (1):test1rank为1,test2rank为1,因此我的旗帜值应为same_rank

2)SID (b)和SSection (2):test1rank为2,test2rank为3此处的排名已更改,因此我的标记值应为rank_changed

3)SID (d)和SSection (4):在test1rank中为2,在test2rank中他失去了排名,因此我的旗帜值应为No_rank 4)SID (f)和SSection (4):在test1rank中他没有表现好,所以他没有任何等级,在test2rank他表现不错,他的等级是2,所以我的旗帜值应该是{ {1}}

1 个答案:

答案 0 :(得分:1)

这可以给你你想要的东西:

from pyspark.sql import functions as f

test3=test1.withColumnRenamed('SRank','test1SRank')\
    .join(test2.drop('SSection')\
    .withColumnRenamed('SRank','test2SRank'), on='SID', how='outer')\
    .fillna(0)

test3=test3.withColumn('flag', f.expr("case when test1SRank=0 and test2SRank>0 then 'new_rank'\
                                            when test1SRank>0 and test2SRank=0 then 'No_rank'\
                                            when test1SRank=test2SRank then 'same_rank'\
                                            else 'rank_changed' end"))
test3.orderBy('SID').show()

说明:外部加入数据框,因此您拥有所有SID的test1和test2分数。然后用0填充空值,并在语句时使用sql case执行标志逻辑。