Apache spark Pyspark:将UDF的结果迭代地写回dataframe不会产生预期的结果
我仍然是pyspark的新手,我试图在UDF的帮助下对函数求值并迭代创建列。功能如下:Apache spark Pyspark:将UDF的结果迭代地写回dataframe不会产生预期的结果,apache-spark,pyspark,spark-dataframe,pyspark-sql,apache-spark-2.0,Apache Spark,Pyspark,Spark Dataframe,Pyspark Sql,Apache Spark 2.0,我仍然是pyspark的新手,我试图在UDF的帮助下对函数求值并迭代创建列。功能如下: def get_temp(df): l=['temp1','temp2','temp3'] s=[0] pt=[0] 开始=[0] 结束=[0] 累积统计=[0] 对于X范围内的p(1,4): def func(p): 如果p==1: 通过 如果p>1: 开始[0]=结束[0] s[0]=2 pt[0]=4 结束[0]=开始[0]+pt[0]-s[0] 返回端[0] func_udf=udf(func,Int
def get_temp(df):
l=['temp1','temp2','temp3']
s=[0]
pt=[0]
开始=[0]
结束=[0]
累积统计=[0]
对于X范围内的p(1,4):
def func(p):
如果p==1:
通过
如果p>1:
开始[0]=结束[0]
s[0]=2
pt[0]=4
结束[0]=开始[0]+pt[0]-s[0]
返回端[0]
func_udf=udf(func,IntegerType())
df=df.带列(l[p-1],func_udf(lit(p)))
返回df
df=获取温度(df)
df.show()
上述结果如下:
+---+---+---+-----+-----+-----+
|a | b | c | temp1 | temp2 | temp3|
+---+---+---+-----+-----+-----+
| 2| 12| 5| 0| 2| 2|
| 8| 5| 7| 0| 4| 4|
| 9| 4| 3| 0| 2| 2|
| 3| 8| 2| 0| 4| 4|
+---+---+---+-----+-----+-----+
预期结果是:
+---+---+---+-----+-----+-----+
|a | b | c | temp1 | temp2 | temp3|
+---+---+---+-----+-----+-----+
| 2| 12| 5| 0| 2| 4|
| 8| 5| 7| 0| 2| 4|
| 9| 4| 3| 0| 2| 4|
| 3| 8| 2| 0| 2| 4|
+---+---+---+-----+-----+-----+
如果仅查看内部函数的输出,结果与预期一致,即:
s=[0]
pt=[0]
开始=[0]
结束=[0]
累积统计=[0]
对于X范围内的p(1,4):
def func():
如果p==1:
通过
如果p>1:
开始[0]=结束[0]
s[0]=2
pt[0]=4
结束[0]=开始[0]+pt[0]-s[0]
返回端[0]
e=func()
打印e
输出:
0
2.
4.
不确定将这些结果从UDF写回df的正确方法是什么。发布的dataframe只是一个示例dataframe,我需要使用for循环,因为在我的原始代码中,我调用了for循环中的其他函数(谁的输出取决于迭代器的值)。例如,请参阅下面的示例:
def get_temp(df):
l=['temp1','temp2','temp3']
s=[0]
pt=[0]
开始=[0]
结束=[0]
q=[]
累积统计=[0]
对于X范围内的p(1,4):
def func(p):
如果p=a:
如果p==1:
通过
如果p>1:
开始[0]=结束[0]
s[0]=2
pt[0]=4
如果累积统计和p>1:
var1=func2(p,3000)
var2=func3(var1)
累积统计=np.nan
其他:
var1=func2(p,3000)
var2=func3(var1)
结束[0]=开始[0]+pt[0]-s[0]
q、 追加(结束[0],变量1,变量2)
返回q
func_udf=udf(func,ArrayType(ArrayType(IntegerType()))
df=df.带列(l[p-1],func_udf(lit(p)))
返回df
df=获取温度(df)
df.show()
我正在使用pyspark 2.2。非常感谢您的帮助。
要创建此数据帧,请执行以下操作:
rdd=sc.parallelize([(2,12,5),(8,5,7),
(9,4,3),
(3,8,2)])
df=sqlContext.createDataFrame(rdd,('a','b','c'))
df.show()
根据我对代码的理解,下一列的值取决于上一列的值。如果我的理解是正确的,那么我可以判断您的udf函数定义放在了错误的位置。你需要对你的代码做一些小的修改才能让它正常工作
让我们一步一步走
你已经有了
+---+---+---+
| a| b| c|
+---+---+---+
| 2| 12| 5|
| 8| 5| 7|
| 9| 4| 3|
| 3| 8| 2|
+---+---+---+
我们需要一个初始值设定项列,我看到它是0
应该是哪一个
+---+---+---+-----+
| a| b| c|temp0|
+---+---+---+-----+
| 2| 12| 5| 0|
| 8| 5| 7| 0|
| 9| 4| 3| 0|
| 3| 8| 2| 0|
+---+---+---+-----+
我们应该将udf
函数作为
并在循环中调用udf
函数
最后删除初始值设定项列
这将为您提供所需的输出
+---+---+---+-----+-----+-----+
| a| b| c|temp1|temp2|temp3|
+---+---+---+-----+-----+-----+
| 2| 12| 5| 0| 2| 4|
| 8| 5| 7| 0| 2| 4|
| 9| 4| 3| 0| 2| 4|
| 3| 8| 2| 0| 2| 4|
+---+---+---+-----+-----+-----+
我希望答案是有帮助的为什么要使用udf?这可能是一个问题吗?你想干什么?可能有一种更简单的方法。@pault我用示例代码更新了问题。我想使用udf,因为我确实在其中进行了其他函数调用,并最终对调用的函数进行了一些数学运算并返回了一个输出。上面显示的函数:func对其他函数调用进行计算由于不同列的函数不同,我建议您为每列编写不同的函数,并分别调用它们。请您进一步说明这一点好吗?我不确定如何将其解耦为单独的函数,因为累积_stat是根据在上一次迭代中获得的值进行计算的。谢谢
def func(p, end):
start = 0
s = 0
pt = 0
if p==1:
pass
elif p >1:
start = end
s=2
pt =4
end = start + pt - s
return end
func_udf=F.udf(func, T.IntegerType())
def get_temp(df):
l=['temp1','temp2','temp3']
for p in xrange(1,4):
df=df.withColumn(l[p-1],func_udf(F.lit(p), F.col('temp'+str(p-1))))
return df
df=get_temp(df)
df=df.drop('temp0')
+---+---+---+-----+-----+-----+
| a| b| c|temp1|temp2|temp3|
+---+---+---+-----+-----+-----+
| 2| 12| 5| 0| 2| 4|
| 8| 5| 7| 0| 2| 4|
| 9| 4| 3| 0| 2| 4|
| 3| 8| 2| 0| 2| 4|
+---+---+---+-----+-----+-----+