Pyspark 使用特定条件更新数据帧

Pyspark 使用特定条件更新数据帧,pyspark,user-defined-functions,pyspark-sql,Pyspark,User Defined Functions,Pyspark Sql,我的数据框架如下: RankNumber Value Dept Number 5 200 5 4 200 5 3 205 5 2 198 5 1 197 5 5 200 6 4 202 6 3 205 6 2 198 6 1

我的数据框架如下:

RankNumber  Value   Dept Number
  5          200    5
  4          200    5
  3          205    5
  2          198    5
  1          197    5
  5          200    6
  4          202    6
  3          205    6
  2          198    6
  1          194    6
我想从dataframe中的Value列更新一些单元格。如果当前“值”大于以前的值,则应将其更新为以前的值。如果“值”与之前的值相同或小于,则应跳过。它已按部门编号分组

我试图在pyspark上实现这一点,但找不到实现这一点的方法。有人能帮忙吗

dataframe的预期结果如下:

RankNumber  Value  Dept Number
  5         200     5
  4         200     5
  3         200     5 (record updated)
  2         198     5
  1         197     5
  5         200     6
  4         200     6 (record updated)
  3         200     6 (record updated)
  2         198     6
  1         194     6



我相信您的第八行将更新为“
3 202 6(记录更新)
”,而不是 “
32006(记录更新)
”。因为它以前的值是“
202
”,而当前值“
205
”大于以前的“
202

from pyspark.sql.window import Window
import pyspark.sql.functions as F

w=Window.partitionBy("DeptNumber").orderBy(desc("RankNumber"))
df = df.withColumn('previous_value',F.coalesce(F.lag(df['value'],1).over(w),df['value']))
如果值大于上一个值,下面的代码将获得上一个值

newdf = df.select(df.RankNumber,df.DeptNumber,df.Value,df.previous_value,when( df.Value<=df.previous_value, df.Value).otherwise(df.previous_value).alias('newValue'))

>>> newdf.show()
+----------+----------+-----+--------------+--------+
|RankNumber|DeptNumber|Value|previous_value|newValue|
+----------+----------+-----+--------------+--------+
|         5|         6|  200|           200|     200|
|         4|         6|  202|           200|     200|
|         3|         6|  205|           202|     202|
|         2|         6|  198|           205|     198|
|         1|         6|  194|           198|     194|
|         5|         5|  200|           200|     200|
|         4|         5|  200|           200|     200|
|         3|         5|  205|           200|     200|
|         2|         5|  198|           205|     198|
|         1|         5|  197|           198|     197|
+----------+----------+-----+--------------+--------+
w1=Window.partitionBy("DeptNumber").orderBy(desc("RankNumber"))
w2=Window.partitionBy("DeptNumber").orderBy(desc("RankNumber")).rowsBetween(Window.unboundedPreceding, Window.currentRow)

df = df.withColumn('previous_value',F.coalesce(F.lag(df['value'],1).over(w1),df['value']))
更新: 现在创建一个新的dataframe,如下面的注释部分所述:

listOfTuples = [(5, 200, "Dept1"), (4, 202, "Dept1"), (3, 205, "Dept1"), (2, 198, "Dept1"), (1, 194, "Dept1") , (5, 100, "Dept2"), (4, 102, "Dept2"), (3, 105, "Dept2"), (2, 198, "Dept2"), (1, 194, "Dept2") ]

df = spark.createDataFrame(listOfTuples , ["RankNumber", "Value", "DeptNumber"])


>>> df.show()
+----------+-----+----------+
|RankNumber|Value|DeptNumber|
+----------+-----+----------+
|         5|  200|     Dept1|
|         4|  202|     Dept1|
|         3|  205|     Dept1|
|         2|  198|     Dept1|
|         1|  194|     Dept1|
|         5|  100|     Dept2|
|         4|  102|     Dept2|
|         3|  105|     Dept2|
|         2|  198|     Dept2|
|         1|  194|     Dept2|
+----------+-----+----------+
我相信您的意图是查看当前行和前一行之间的范围,如果第一个条件得到满足,则选择最低值。ie:值大于以前的值

newdf = df.select(df.RankNumber,df.DeptNumber,df.Value,df.previous_value,when( df.Value<=df.previous_value, df.Value).otherwise(df.previous_value).alias('newValue'))

>>> newdf.show()
+----------+----------+-----+--------------+--------+
|RankNumber|DeptNumber|Value|previous_value|newValue|
+----------+----------+-----+--------------+--------+
|         5|         6|  200|           200|     200|
|         4|         6|  202|           200|     200|
|         3|         6|  205|           202|     202|
|         2|         6|  198|           205|     198|
|         1|         6|  194|           198|     194|
|         5|         5|  200|           200|     200|
|         4|         5|  200|           200|     200|
|         3|         5|  205|           200|     200|
|         2|         5|  198|           205|     198|
|         1|         5|  197|           198|     197|
+----------+----------+-----+--------------+--------+
w1=Window.partitionBy("DeptNumber").orderBy(desc("RankNumber"))
w2=Window.partitionBy("DeptNumber").orderBy(desc("RankNumber")).rowsBetween(Window.unboundedPreceding, Window.currentRow)

df = df.withColumn('previous_value',F.coalesce(F.lag(df['value'],1).over(w1),df['value']))
这是您的代码:

newdf = df.select(df.RankNumber,df.DeptNumber,df.Value,df.previous_value,when( df.Value<=df.previous_value, df.Value) \
                        .otherwise(F.min(df.previous_value).over(w2)).alias('newValue'))

>>> newdf.show()
+----------+----------+-----+--------------+--------+
|RankNumber|DeptNumber|Value|previous_value|newValue|
+----------+----------+-----+--------------+--------+
|         5|     Dept2|  100|           100|     100|
|         4|     Dept2|  102|           100|     100|
|         3|     Dept2|  105|           102|     100|
|         2|     Dept2|  198|           105|     100|
|         1|     Dept2|  194|           198|     194|
|         5|     Dept1|  200|           200|     200|
|         4|     Dept1|  202|           200|     200|
|         3|     Dept1|  205|           202|     200|
|         2|     Dept1|  198|           205|     198|
|         1|     Dept1|  194|           198|     194|
+----------+----------+-----+--------------+--------+
newdf=df.select(df.RankNumber,df.DeptNumber,df.Value,df.previous_值,当(df.Value>>newdf.show()时)
+----------+----------+-----+--------------+--------+
|RankNumber | DeptNumber |值|上一个|值|新值|
+----------+----------+-----+--------------+--------+
|5 | Dept2 | 100 | 100 | 100|
|4 |部门2 | 102 | 100 | 100|
|3 |部门2 | 105 | 102 | 100|
|2 |部门2 | 198 | 105 | 100|
|1 |部门2 | 194 | 198 | 194|
|5 |部门1 | 200 | 200 | 200|
|4 |部门1 | 202 | 200 | 200|
|3 |部门1 | 205 | 202 | 200|
|2 |部门1 | 198 | 205 | 198|
|1 |部门1 | 194 | 198 | 194|
+----------+----------+-----+--------------+--------+

谢谢@Vikrant的回复,你答对了。说第7条记录“42002,6”将更新为第6条记录“4200,6”.由于第5条记录的值小于第6条记录的值,这有意义吗?谢谢。因此,您希望得到问题中提到的输出。我认为这是可以做到的。必须还有一个延迟。一旦进入系统,我将尝试一下。:-)我明白您的意思,可能是这样的。.将解决问题
df=df.withColumn('prepre_value',F.coalesce(F.lag(df['previous_value'],1).over(w),df['previous_value']))
但是我们如何知道要应用的滞后数量,因为这需要动态完成,并且不能通过查看数据集来接听电话。感谢您的帮助。不用担心。慢慢来我指的是记录“rankNumber=1,DeptNumber=Dept2”新值为194。其中,RankNumber=2的前一行的新值为100。没关系,我已将此标记为已回答并已完成。我将整理其余内容。非常感谢您的努力和帮助!非常感谢!祝您度过愉快的一天
newdf = df.select(df.RankNumber,df.DeptNumber,df.Value,df.previous_value,when( df.Value<=df.previous_value, df.Value) \
                        .otherwise(F.min(df.previous_value).over(w2)).alias('newValue'))

>>> newdf.show()
+----------+----------+-----+--------------+--------+
|RankNumber|DeptNumber|Value|previous_value|newValue|
+----------+----------+-----+--------------+--------+
|         5|     Dept2|  100|           100|     100|
|         4|     Dept2|  102|           100|     100|
|         3|     Dept2|  105|           102|     100|
|         2|     Dept2|  198|           105|     100|
|         1|     Dept2|  194|           198|     194|
|         5|     Dept1|  200|           200|     200|
|         4|     Dept1|  202|           200|     200|
|         3|     Dept1|  205|           202|     200|
|         2|     Dept1|  198|           205|     198|
|         1|     Dept1|  194|           198|     194|
+----------+----------+-----+--------------+--------+