Selección de valores de matriz vacía de un Spark DataFrame

Dado un DataFrame con las siguientes filas:

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

Me gustaría eliminar las filas con una matriz vacía para cada uno de col2 , col4 y col4 (es decir, la tercera fila).

Por ejemplo, podría esperar que este código funcione:

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

Tengo dos problemas

  1. cómo combinar las cláusulas con and pero lo más importante …
  2. cómo determinar si la matriz está vacía.

Entonces, ¿hay una función incorporada para consultar matrices vacías? ¿Existe una forma elegante de forzar una matriz vacía a un valor n o null ?

Estoy intentando evitar usar Python para resolverlo, ya sea con un UDF o .map() .

cómo combinar las cláusulas con y

Para construir expresiones booleanas en columnas, debe usar & , | y ~ operadores así que en tu caso debería ser algo como esto

 ~lit(True) & ~lit(False) 

Dado que estos operadores tienen mayor prioridad que los operadores de comparación para expresiones complejas, tendrá que usar paréntesis:

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

cómo determinar si la matriz está vacía.

Estoy bastante seguro de que no hay una forma elegante de manejar esto sin un UDF. Supongo que ya sabes que puedes usar un UDF de Python como este

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

También es posible utilizar un UDF Hive:

 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) 

La única solución factible que no sea UDF que se me ocurra es convertirla en una cadena

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

pero huele desde una milla de distancia.

También es posible explode una matriz, groupBy , agg usando count y join pero lo más probable es que sea muy caro para ser útil en cualquier escenario de la vida real.

Probablemente el mejor enfoque para evitar UDF y hacks sucios es reemplazar los arreglos vacíos con NULL .