Python RuntimeError:来自pandas_udf的结果向量不是所需的长度:应为2,得到1
我正在尝试使用Python RuntimeError:来自pandas_udf的结果向量不是所需的长度:应为2,得到1,python,pandas,apache-spark,pyspark,user-defined-functions,Python,Pandas,Apache Spark,Pyspark,User Defined Functions,我正在尝试使用pandas\u udf 我有我的Spark数据框,其中有一个数组列Struct: root |-- values: array (nullable = true) | |-- element: struct (containsNull = true) | | |-- x: double (nullable = true) | | |-- y: double (nullable = true) 我想做的是在values列上运行pandas_u
pandas\u udf
我有我的Spark数据框,其中有一个数组列Struct:
root
|-- values: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- x: double (nullable = true)
| | |-- y: double (nullable = true)
我想做的是在values
列上运行pandas_udf,并根据定义的逻辑为每个记录(即每个数组)返回一个值
在我的数据源中,如果有多条记录的values
列包含空数组,则会出现以下错误:
line 89, in verify_result_length "expected %d, got %d" % (len(a[0]), len(result)))
RuntimeError: Result vector from pandas_udf was not the required length: expected 2, got 1
在Google上搜索时,我在此处找到了源代码:
另一方面,如果我只有一条带有空数组的记录,那么进程将毫无问题地结束。使用空数组筛选Spark记录没有帮助(仅供参考.filter(“大小(值)!=0”)
),它会导致相同的行为
但我不明白为什么我会犯这个错误,我做错了什么。有人能帮忙吗
编辑
代码:
import numpy as np
import pandas as pd
import pyspark.sql.functions as f
udf = f.pandas_udf(udf_function, returnType="float")
df.withColumn("newColumn",
f.when(f.size(f.col("values")) == 0, 0)\
.otherwise(udf(f.col("values.x"), f.col("values.y"))))
def udf_function(x_array, y_array, Window=20):
xy = []
data = pd.DataFrame({'x': x_array.tolist()[0], 'y': y_array.tolist()[0]})
x = data['x'].rolling(int(Window / 2), center=True, min_periods=1).sum()
y = data['y'].rolling(int(Window / 2), center=True, min_periods=1).sum()
for index in range(len(x)):
xy.append(np.sqrt(x[index] ** 2 + y[index] ** 2))
if not xy:
result = 0
else:
result = max(xy)
return pd.Series(result)
{
"values": []
}
{
"values": []
}
{
"values": [
{
"x": -0.638,
"y": 0.879,
},
{
"x": -0.616,
"y": 0.809,
},
{
"x": -0.936,
"y": 0.762,
}]
}
记录:
import numpy as np
import pandas as pd
import pyspark.sql.functions as f
udf = f.pandas_udf(udf_function, returnType="float")
df.withColumn("newColumn",
f.when(f.size(f.col("values")) == 0, 0)\
.otherwise(udf(f.col("values.x"), f.col("values.y"))))
def udf_function(x_array, y_array, Window=20):
xy = []
data = pd.DataFrame({'x': x_array.tolist()[0], 'y': y_array.tolist()[0]})
x = data['x'].rolling(int(Window / 2), center=True, min_periods=1).sum()
y = data['y'].rolling(int(Window / 2), center=True, min_periods=1).sum()
for index in range(len(x)):
xy.append(np.sqrt(x[index] ** 2 + y[index] ** 2))
if not xy:
result = 0
else:
result = max(xy)
return pd.Series(result)
{
"values": []
}
{
"values": []
}
{
"values": [
{
"x": -0.638,
"y": 0.879,
},
{
"x": -0.616,
"y": 0.809,
},
{
"x": -0.936,
"y": 0.762,
}]
}
另外,即使使用f.when(f.size(f.col(“values”)==0,0)。否则(udf())
条件应该过滤掉带有空数组的记录(或者至少在空数组的情况下,不应该调用udf函数),看起来udf函数无论如何都会处理这些记录!这对我来说很奇怪
进一步的上下文:
import numpy as np
import pandas as pd
import pyspark.sql.functions as f
udf = f.pandas_udf(udf_function, returnType="float")
df.withColumn("newColumn",
f.when(f.size(f.col("values")) == 0, 0)\
.otherwise(udf(f.col("values.x"), f.col("values.y"))))
def udf_function(x_array, y_array, Window=20):
xy = []
data = pd.DataFrame({'x': x_array.tolist()[0], 'y': y_array.tolist()[0]})
x = data['x'].rolling(int(Window / 2), center=True, min_periods=1).sum()
y = data['y'].rolling(int(Window / 2), center=True, min_periods=1).sum()
for index in range(len(x)):
xy.append(np.sqrt(x[index] ** 2 + y[index] ** 2))
if not xy:
result = 0
else:
result = max(xy)
return pd.Series(result)
{
"values": []
}
{
"values": []
}
{
"values": [
{
"x": -0.638,
"y": 0.879,
},
{
"x": -0.616,
"y": 0.809,
},
{
"x": -0.936,
"y": 0.762,
}]
}
当我使用大约15个或更多的输入文件时,出现了一个例外,这与使用空数组的记录无关。无论如何,这是一个奇怪的异常,因为对于观察到的行为,我期待类似“JavaOutOfMemory异常”的东西,但报告的异常对我理解真正的问题没有太大帮助
与此同时,我回来时使用了更多的stables RDD而不是pandas_udf。你能提供一些虚拟数据和你的udf来复制这个问题吗?@pansen编辑!我希望它有助于复制它(如何在Spark中阅读json取决于您),如果您需要其他东西或者您成功地复制了这种情况,请告诉我。您可以使用空数组轻松地增加或减少记录数