如何在pyspark中使用第一个和最后一个函数?

时间:2017-03-30 09:57:10

标签: apache-spark pyspark

我使用第一个和最后一个函数来获取一列的第一个和最后一个值。但是,我发现这两个功能都不像我想的那样工作。我提到了answer @zero323,但我仍然对这两者感到困惑。代码如:

df = spark.sparkContext.parallelize([
    ("a", None), ("a", 1), ("a", -1), ("b", 3), ("b", 1)
]).toDF(["k", "v"])
w = Window().partitionBy("k").orderBy('k','v')

df.select(F.col("k"), F.last("v",True).over(w).alias('v')).show()

结果:

+---+----+
|  k|   v|
+---+----+
|  b|   1|
|  b|   3|
|  a|null|
|  a|  -1|
|  a|   1|
+---+----+

我认为应该是这样的:

+---+----+
|  k|   v|
+---+----+
|  b|   3|
|  b|   3|
|  a|   1|
|  a|   1|
|  a|   1|
+---+----+

因为我通过orderBy的操作显示了df' k'和' v':

df.orderBy('k','v').show()
    +---+----+
    |  k|   v|
    +---+----+
    |  a|null|
    |  a|  -1|
    |  a|   1|
    |  b|   1|
    |  b|   3|
    +---+----+

另外,我想出了另一个测试这类问题的解决方案,我的代码如下:

df.orderBy('k','v').groupBy('k').agg(F.first('v')).show()

我发现每次运行它之后它的结果可能会有所不同。有人遇到过和我一样的经历吗?我希望在我的项目中使用这两个函数,但我发现这些解决方案是不确定的。

2 个答案:

答案 0 :(得分:8)

尝试使用.desc()反转排序顺序,然后first()将提供所需的输出。

w2 = Window().partitionBy("k").orderBy(df.v.desc())
df.select(F.col("k"), F.first("v",True).over(w2).alias('v')).show()
F.first("v",True).over(w2).alias('v').show()

输出:

+---+---+
|  k|  v|
+---+---+
|  b|  3|
|  b|  3|
|  a|  1|
|  a|  1|
|  a|  1|
+---+---+

你应该注意partitionBy和orderBy。由于您使用'k'进行分区,因此任何给定窗口中的k的所有值都是相同的。按'k'排序什么都不做。

最后一个函数与第一个函数实际上并不相反,就它返回的窗口中的哪个项而言。它返回它看到的最后一个非null值,因为它在有序行中前进。

为了比较它们的效果,这里是一个包含功能/排序组合的数据帧。注意如何在列'last_w2'中,空值已被-1替换。

df = spark.sparkContext.parallelize([
    ("a", None), ("a", 1), ("a", -1), ("b", 3), ("b", 1)]).toDF(["k", "v"])

#create two windows for comparison.
w = Window().partitionBy("k").orderBy('v')
w2 = Window().partitionBy("k").orderBy(df.v.desc())

df.select('k','v',
   F.first("v",True).over(w).alias('first_w1'),
   F.last("v",True).over(w).alias('last_w1'),
   F.first("v",True).over(w2).alias('first_w2'),
   F.last("v",True).over(w2).alias('last_w2')
).show()

输出:

+---+----+--------+-------+--------+-------+
|  k|   v|first_w1|last_w1|first_w2|last_w2|
+---+----+--------+-------+--------+-------+
|  b|   1|       1|      1|       3|      1|
|  b|   3|       1|      3|       3|      3|
|  a|null|    null|   null|       1|     -1|
|  a|  -1|      -1|     -1|       1|     -1|
|  a|   1|      -1|      1|       1|      1|
+---+----+--------+-------+--------+-------+

答案 1 :(得分:1)

看看Question 47130030
问题不在于last()函数,而在于框架,该框架仅包括直到当前的行。
使用

w = Window().partitionBy("k").orderBy('k','v').rowsBetween(W.unboundedPreceding,W.unboundedFollowing)

将为first()和last()产生正确的结果。