当前位置: 首页 > 知识库问答 >
问题:

Pyspark窗口函数在其他列上带有过滤器

聂翼
2023-03-14

我有一个包含以下数据的pyspark dataframe:

| y | date       | amount| id |
 ----------------------------- 
| 1 | 2017-01-01 | 10    | 1  |
| 0 | 2017-01-01 | 2     | 1  |
| 1 | 2017-01-02 | 20    | 1  |
| 0 | 2017-01-02 | 3     | 1  |
| 1 | 2017-01-03 | 2     | 1  |
| 0 | 2017-01-03 | 5     | 1  |
w = Window \
        .partitionBy(df.id) \
        .orderBy(df.date.asc()) \
        .rowsBetween(Window.unboundedPreceding, -1)
| y | date       | amount| id | sum |
 ----------------------------------- 
| 1 | 2017-01-01 | 10    | 1  | 0   |
| 0 | 2017-01-01 | 2     | 1  | 0   |
| 1 | 2017-01-02 | 20    | 1  | 10  | // =10 (considering only the row with y==1)
| 0 | 2017-01-02 | 3     | 1  | 10  | // same as above
| 1 | 2017-01-03 | 2     | 1  | 30  | // =10+20
| 0 | 2017-01-03 | 5     | 1  | 30  | // same as above

共有1个答案

白嘉志
2023-03-14

实际上,使用一个窗口函数很难处理它。我认为您应该先创建一些虚拟列来计算和列。你可以在下面找到我的解决方案。

>>> from pyspark.sql.window import Window
>>> import pyspark.sql.functions as F
>>> 
>>> df.show()
+---+----------+------+---+
|  y|      date|amount| id|
+---+----------+------+---+
|  1|2017-01-01|    10|  1|
|  0|2017-01-01|     2|  1|
|  1|2017-01-02|    20|  1|
|  0|2017-01-02|     3|  1|
|  1|2017-01-03|     2|  1|
|  0|2017-01-03|     5|  1|
+---+----------+------+---+

>>> 
>>> df = df.withColumn('c1', F.when(F.col('y')==1,F.col('amount')).otherwise(0))
>>> 
>>> window1 = Window.partitionBy(df.id).orderBy(df.date.asc()).rowsBetween(Window.unboundedPreceding, -1)
>>> df = df.withColumn('c2', F.sum(df.c1).over(window1)).fillna(0)
>>> 
>>> window2 = Window.partitionBy(df.id).orderBy(df.date.asc())
>>> df = df.withColumn('c3', F.lag(df.c2).over(window2)).fillna(0)
>>> 
>>> df = df.withColumn('sum', F.when(df.y==0,df.c3).otherwise(df.c2))
>>> 
>>> df = df.select('y','date','amount','id','sum')
>>> 
>>> df.show()
+---+----------+------+---+---+                                                 
|  y|      date|amount| id|sum|
+---+----------+------+---+---+
|  1|2017-01-01|    10|  1|  0|
|  0|2017-01-01|     2|  1|  0|
|  1|2017-01-02|    20|  1| 10|
|  0|2017-01-02|     3|  1| 10|
|  1|2017-01-03|     2|  1| 30|
|  0|2017-01-03|     5|  1| 30|
+---+----------+------+---+---+

如果每天有多个y=1或y=0行,则此解决方案可能不起作用,请考虑

 类似资料:
  • 问题内容: 这段代码可以正常工作,但是我又长又令人毛骨悚然。 如您所见,它由3个重复部分组成,用于检索: 玩家名称和他们玩过的游戏数量 玩家名称和他们赢得的游戏数量 玩家姓名和输掉的游戏数量 并且每个还包括2个部分: 玩家名称和以玩家_1身份参加的游戏数量 玩家名称以及他们作为玩家_2参加的游戏数量 如何简化呢? 结果看起来像这样: 问题答案: Postgres 9.4* 或更高版本中的 聚合子句

  • 问题内容: 这是该问题的后续内容,其中对我的查询进行了改进,使其使用窗口函数而不是联接内的聚合。虽然查询现在快得多,但我发现结果不正确。 我需要在x年尾随时间框架上执行计算。例如,每行的计算方法是:十年前移至当前行,然后除以结果。为了简单起见,我们将使用1年。 SQL Fiddle对此问题进行了解答。(Postgres 9.6) 作为一个简单的例子,和用于可像这样分别计算: 要做到这一点 ,每行

  • 下面是一些示例代码: 这是我希望看到的输出:

  • 问题内容: 好的,起初这只是和我的一个朋友开玩笑,但后来变成了有趣的技术问题:) 我有下表: 该表包含我所有东西的记录,并分别具有数量和优先级(我需要多少)。 我有一个指定体积的袋子,例如。我想从表中选择所有可以放入袋子的东西,首先包装最重要的东西。 这似乎是使用窗口函数的情况,所以这是我想出的查询: 但是,问题在于Postgres抱怨: 如果我删除此过滤器,则会正确计算总列,对结果进行正确排序,

  • 我有以下数据: 现在我想以这样一种方式过滤数据,我可以删除第6行和第7行,对于特定的uid,我想在代码中只保留一行值为'c' 所以预期的数据应该是: 我使用的窗口函数如下所示:

  • 问题内容: 我将Python 2与和一起使用,然后使用。 该程序运行良好,但是每次打开该程序时,窗口都会显示为隐藏状态,因此,直到我单击扩展坞上的图标以将其打开时,该窗口才会出现。 有什么方法可以控制此,使该窗口位于应用程序启动时打开的其他窗口之上? 需要澄清的是,在应用程序运行的整个过程中,它不一定都位于最前面。我只需要它在启动时位于其他窗口之上。 问题答案: 如果我接受您提供的代码并添加第一行