Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
pyspark数据帧上的复杂逻辑,包括前一行现有值以及动态生成的前一行值_Pyspark - Fatal编程技术网

pyspark数据帧上的复杂逻辑,包括前一行现有值以及动态生成的前一行值

pyspark数据帧上的复杂逻辑,包括前一行现有值以及动态生成的前一行值,pyspark,Pyspark,我必须在spark dataframe或rdd(最好是dataframe)上应用逻辑,这需要生成两个额外的列。第一个生成的列依赖于同一行的其他列,第二个生成的列依赖于前一行的第一个生成列 以下是问题陈述的表格形式。A和B列在dataframe中可用。将生成C和D列 A | B | C | D ------------------------------------ 1 | 100 | default val | C1-B1 2 | 200 | D

我必须在spark dataframe或rdd(最好是dataframe)上应用逻辑,这需要生成两个额外的列。第一个生成的列依赖于同一行的其他列,第二个生成的列依赖于前一行的第一个生成列

以下是问题陈述的表格形式。A和B列在dataframe中可用。将生成C和D列

A |  B   | C            |     D
------------------------------------
1 | 100  |  default val |    C1-B1
2 | 200  |  D1-C1       |    C2-B2
3 | 300  |  D2-C2       |    C3-B3
4 | 400  |  D3-C3       |    C4-B4
5 | 500  |  D4-C4       |    C5-B5
下面是示例数据

A |  B   |    C   |   D
------------------------
1 | 100  |   1000 |  900
2 | 200  |  -100  | -300
3 | 300  |  -200  | -500
4 | 400  |  -300  | -700
5 | 500  |  -400  | -900
我能想到的唯一解决方案是将输入数据帧合并为1,将其转换为rdd,然后将python函数(具有所有计算逻辑)应用于mapPartitions API。
然而,这种方法可能会在一个执行器上产生负载。

从数学上看,D1-C1,其中D1=C1-B1;因此D1-C1将变成C1-B1-C1=>-B1。 在pyspark中,window函数有一个名为default的参数。这将简化您的问题。试试这个:

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

df = spark.createDataFrame([(1,100),(2,200),(3,300),(4,400),(5,500)],['a','b'])
w=Window.orderBy('a')
df_lag =df.withColumn('c',F.lag((F.col('b')*-1),default=1000).over(w))
df_final = df_lag.withColumn('d',F.col('c')-F.col('b'))
结果:

df_final.show()
+---+---+----+----+
|  a|  b|   c|   d|
+---+---+----+----+
|  1|100|1000| 900|
|  2|200|-100|-300|
|  3|300|-200|-500|
|  4|400|-300|-700|
|  5|500|-400|-900|
+---+---+----+----+
如果操作不是减法,而是复杂的操作,那么同样的逻辑也适用-用默认值填充C列-计算D,然后使用lag计算C并重新计算D。

lag()函数可能会帮助您:

导入pyspark.sql.F函数
从pyspark.sql.window导入窗口
w=Window.orderBy(“A”)
df1=df1。带柱(“C”,F.lit(1000))
df2=(
df1
.带“D”列,F.col(“C”)-F.col(“B”))
.withColumn(“C”,
F.when(F.lag(“C”).over(w).isNotNull()时,
F.滞后(“D”).超过(w)-F.滞后(“C”).超过(w))
.否则(F.col(“C”))
.带“D”列,F.col(“C”)-F.col(“B”))
)

在该解决方案中,在计算D时,所有行的C值都固定为1000。然而,在问题陈述中,第2行的C列依赖于第1行的D列。另外,在您的解决方案的最后三行中缺少一个(w)。感谢您提供缺少代码的提示。解释为什么我为所有行设置了1000,它是在第一行中设置的默认值,之后使用后续值再次计算C列。无论如何,如果您想使用列的前一个值计算某些内容,lag()函数可能会有所帮助。此代码生成的D列数据为900800700600500,但D列的预期输出为900,-300,-500,-700,-900,这是因为上述代码在进行D列计算时考虑了所有行的默认值C。还有一个小的代码变化在第4行从顶部。您需要再次将输出数据帧分配给df1。在跟随另一个答案中@Raghu的注释之后,我们需要在计算C列之后再次计算D列。这样我们将得到所需的答案。问题陈述中显示的计算用于表示目的。实际计算不是简单的减法。我想要一个解决方案,它可以实现上表中D所示的上一个生成列的依赖关系。@PratekPathak-您也可以将相同的逻辑应用于任何计算。在C列中填入您的默认值——计算d,然后使用lag计算C并重新计算它的有效值。我对你的意见投了赞成票,这是解决办法的要点。我已经接受了泰利斯苏托提供的代码,并根据评论对其进行了修改。@PrateekPathak-很高兴听到这个消息。我看不到对评论的投票。如果答案有帮助,你能投票并接受答案,以便将来对其他人有用吗?(无义务)我也会更新答案以包含评论。