web-dev-qa-db-ja.com

DataFrameで空の文字列をNone / null値に置き換えます

同じ列にnullと空の文字列が混在する Spark 1.5.0 DataFrame があります。すべての列のすべての空の文字列をnull(PythonのNone)に変換したい。 DataFrameには数百の列がある場合があるため、各列のハードコーディングされた操作を回避しようとしています。

以下の私の試みを参照してください。これはエラーになります。

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|
## +----+----+
21
dnlbrky

私のソリューションは、これまで見てきたすべてのソリューションよりもはるかに優れており、必要なだけ多くのフィールドを処理できます。小さな機能は次のとおりです。

  // 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: _*)
  }

上記の関数はPythonで簡単に書き換えることができます。

@ liancheng からこのトリックを学びました

10
soulmachine

Zero323とsoulmachineの答えの上に追加するだけです。すべての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)
7
Robin Loxley

UDFはそれほど効率的ではありません。組み込みメソッドを使用してこれを行う正しい方法は次のとおりです。

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