给定一个包含以下行的 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()
我有两个问题
- 如何将 where 子句与
和结合使用,但更重要的是...... - 如何判断数组是否为空。
那么,是否有内置函数来查询空数组?有没有一种优雅的方法可以将空数组强制为 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 替换空数组。
