Skip to main content
 首页 » 编程设计

python之从 Spark DataFrame 中选择空数组值

2024年08月25日33lori

给定一个包含以下行的 DataFrame:

rows = [ 
    Row(col1='abc', col2=[8], col3=[18], col4=[16]), 
    Row(col2='def', col2=[18], col3=[18], col4=[]), 
    Row(col3='ghi', col2=[], col3=[], col4=[])] 

我想为每个 col2、col3 和 col4(即第 3 行)删除具有空数组的行。

例如,我可能希望这段代码能够工作:

df.where(~df.col2.isEmpty(), ~df.col3.isEmpty(), ~df.col4.isEmpty()).collect() 

我有两个问题

  1. 如何将 where 子句与 和 结合使用,但更重要的是......
  2. 如何判断数组是否为空。

那么,是否有内置函数来查询空数组?有没有一种优雅的方法可以将空数组强制为 na 或 null 值?

我试图避免使用 python 来解决它,无论是使用 UDF 还是 .map()。

请您参考如下方法:

how to combine where clauses with and

要在列上构造 bool 表达式,您应该使用 &、| 和 ~ 运算符,因此在您的情况下应该是这样的

~lit(True) & ~lit(False) 

由于这些运算符的优先级高于复杂表达式的比较运算符,因此您必须使用括号:

(lit(1) > lit(2)) & (lit(3) > lit(4)) 

how to determine if the array is empty.

我很确定没有 UDF 就没有优雅的方法来处理这个问题。我想您已经知道可以像这样使用 Python UDF

isEmpty = udf(lambda x: len(x) == 0, BooleanType()) 

也可以使用 Hive UDF:

df.registerTempTable("df") 
query = "SELECT * FROM df WHERE {0}".format( 
  " AND ".join("SIZE({0}) > 0".format(c) for c in ["col2", "col3", "col4"])) 
 
sqlContext.sql(query) 

想到的唯一可行的非UDF解决方案是转换为字符串

cols = [ 
    col(c).cast(StringType()) != lit("ArrayBuffer()") 
    for c in  ["col2", "col3", "col4"] 
] 
cond = reduce(lambda x, y: x & y, cols) 
df.where(cond) 

但它在一英里外闻起来。

也可以使用 count 和 join explode 数组,groupBy,agg 但在任何现实生活场景中使用起来很可能非常昂贵。

避免 UDF 和肮脏黑客攻击的最佳方法可能是用 NULL 替换空数组。