我在Spark数据框中有数据,其中col
列包含以下格式的结构化数据:
------ col ------- # Column whose elements are structures
field0 field1 … # StructType with StructFields (variable names and count)
[1,2,3] [4,5] [6] # Each field is of type ArrayType
[1,2] [3] []
…
其中字段的编号和名称未修复。
计算每一行中元素总数的最有效方法是什么?在上面的示例中,预期的结果数据框将是:
num_elements
6
3
…
始终存在用户定义函数的解决方案:
from pyspark.sql.types import IntegerType
def num_elements(all_arrays_in_row):
return sum(map(len, all_arrays_in_row))
num_elements = pyspark.sql.functions.udf(num_elements, IntegerType())
data_frame.select(num_elements(data_frame.col)).show() # Number of elements in each row
现在,我不确定这是否通常有效,因为:
num_elements()
在Python中。map()
强制在计算每个数组之前获取每个数组。更一般地说,"纯粹" Spark方法会更有效率,但它正在躲避我。到目前为止我尝试的是以下内容,但这比上面的方法更麻烦,而且还不完整:
field0
(繁琐)获取字段名称[field.name for field in data_frame.select("col").schema.fields[0].dataType.fields]
等。对于每个字段名称,有效地计算其数组的大小:
sizes_one_field = data_frame.select(pyspark.sql.functions.size(
data_frame.col.getField(field_name))
现在,我陷入困境,因为我不确定如何将1列数据帧sizes_one_field
加在一起(每个字段名称都有一个)。另外,也许有一种方法可以直接将size()
函数应用于Spark中的col
列的每个字段(通过某种映射?)?或者采用一些完全不同的方法来获取每一行中的元素总数?
答案 0 :(得分:1)
您可以尝试以下内容:
from pyspark.sql import functions as f
result = df.select(sum((f.size(df[col_name]) for col_name in df.columns), f.lit(0)))
此解决方案使用pyspark.sql内置函数,并将以优化的方式执行。有关这些功能的更多信息,您可以查看其pyspark documentation。