with values trying from dropna column python apache-spark dataframe apache-spark-sql pyspark

python - trying - pandas replace null values in column



Reemplace cadenas vacĂ­as con ninguno/valores nulos en DataFrame (5)

Tengo un Spark 1.5.0 DataFrame con una mezcla de cadenas null y vacías en la misma columna. Quiero convertir todas las cadenas vacías en todas las columnas a null ( None , en Python). El DataFrame puede tener cientos de columnas, así que estoy tratando de evitar manipulaciones de cada columna.

Ver mi intento a continuación, lo que resulta en un error.

from pyspark.sql import SQLContext sqlContext = SQLContext(sc) ## Create a test DataFrame testDF = sqlContext.createDataFrame([Row(col1=''foo'', col2=1), Row(col1='''', col2=2), Row(col1=None, col2='''')]) testDF.show() ## +----+----+ ## |col1|col2| ## +----+----+ ## | foo| 1| ## | | 2| ## |null|null| ## +----+----+ ## Try to replace an empty string with None/null testDF.replace('''', None).show() ## ValueError: value should be a float, int, long, string, list, or tuple ## A string value of null (obviously) doesn''t work... testDF.replace('''', ''null'').na.drop(subset=''col1'').show() ## +----+----+ ## |col1|col2| ## +----+----+ ## | foo| 1| ## |null| 2| ## +----+----+


Es tan simple como esto:

from pyspark.sql.functions import col, when def blank_as_null(x): return when(col(x) != "", col(x)).otherwise(None) dfWithEmptyReplaced = testDF.withColumn("col1", blank_as_null("col1")) dfWithEmptyReplaced.show() ## +----+----+ ## |col1|col2| ## +----+----+ ## | foo| 1| ## |null| 2| ## |null|null| ## +----+----+ dfWithEmptyReplaced.na.drop().show() ## +----+----+ ## |col1|col2| ## +----+----+ ## | foo| 1| ## +----+----+

Si desea rellenar varias columnas, por ejemplo, puede reducir:

to_convert = set([...]) # Some set of columns reduce(lambda df, x: df.withColumn(x, blank_as_null(x)), to_convert, testDF)

o utilizar la comprensión:

exprs = [ blank_as_null(x).alias(x) if x in to_convert else x for x in testDF.columns] testDF.select(*exprs)

Si desea operar específicamente en campos de cadenas, verifique la respuesta con robin-loxley .


Esta es una versión diferente de la solución de soulmachine, pero no creo que puedas traducir esto a Python tan fácilmente:

def emptyStringsToNone(df: DataFrame): DataFrame = { df.schema.foldLeft(df)( (current, field) => field.dataType match { case DataTypes.StringType => current.withColumn( field.name, when(length(col(field.name)) === 0, lit(null: String)).otherwise(col(field.name)) ) case _ => current } ) }


Los UDF no son terriblemente eficientes. La forma correcta de hacerlo utilizando un método incorporado es:

df = df.withColumn(''myCol'', when(col(''myCol'') == '''', None).otherwise(col(''myCol'')))


Mi solución es mucho mejor que todas las soluciones que he visto hasta ahora, que pueden ocuparse de tantos campos como desee, vea la pequeña función como la siguiente:

// Replace empty Strings with null values private def setEmptyToNull(df: DataFrame): DataFrame = { val exprs = df.schema.map { f => f.dataType match { case StringType => when(length(col(f.name)) === 0, lit(null: String).cast(StringType)).otherwise(col(f.name)).as(f.name) case _ => col(f.name) } } df.select(exprs: _*) }

Puede reescribir fácilmente la función anterior en Python.

Aprendí este truco de @liancheng


Simplemente agregue encima de las respuestas de zero323 y soulmachine. Para convertir para todos los campos StringType.

from pyspark.sql.types import StringType string_fields = [] for i, f in enumerate(test_df.schema.fields): if isinstance(f.dataType, StringType): string_fields.append(f.name)