Spark Scala Dataframe描述非数字列

时间:2017-01-12 15:59:39

标签: scala apache-spark spark-dataframe apache-spark-mllib data-analysis

对于非数字列,是否存在类似于describe()的函数?

我希望收集有关数据完整性的统计数据'我的桌子。 E.G。

  • 记录总数
  • 空值总数
  • 特殊值的总数(例如0,空字符串等)
  • 不同值的总数
  • 像这样的其他东西......

data.describe()仅为数字列生成有趣的值(count,mean,stddev,min,max)。有没有什么能与字符串或其他类型一起使用?

3 个答案:

答案 0 :(得分:1)

没有。问题是数值数据的基础统计数据很便宜。在分类数据中,其中一些可能需要多次数据扫描,并且无限制(记录数量为线性)内存。

有些很便宜。例如,计数NULL或空:Count number of non-NaN entries in each column of Spark dataframe with Pyspark

答案 1 :(得分:0)

这里有一些代码可以帮助解决分析非数字数据的问题。请参阅:
https://github.com/jasonsatran/spark-meta/

为了提高性能,我们可以对数据进行采样或仅选择我们要显式配置的列。

答案 2 :(得分:0)

以下是获取有问题的字符串列统计信息的示例:

  def getStringColumnProfile(df: DataFrame, columnName: String): DataFrame = {
    df.select(columnName)
      .withColumn("isEmpty", when(col(columnName) === "", true).otherwise(null))
      .withColumn("isNull", when(col(columnName).isNull, true).otherwise(null))
      .withColumn("fieldLen", length(col(columnName)))
      .agg(
        max(col("fieldLen")).as("max_length"),
        countDistinct(columnName).as("unique"),
        count("isEmpty").as("is_empty"),
        count("isNull").as("is_null")
      )
      .withColumn("col_name", lit(columnName))
  }

    def profileStringColumns(df: DataFrame): DataFrame = {
      df.columns.filter(df.schema(_).dataType == StringType)
        .map(getStringColumnProfile(df, _))
        .reduce(_ union _)
        .toDF
        .select("col_name"
          , "unique"
          , "is_empty"
          , "is_null"
          , "max_length")
    }

这与数字列相同

  def getNumericColumnProfile(df: DataFrame, columnName: String): DataFrame = {
    df.select(columnName)
      .withColumn("isZero", when(col(columnName) === 0, true).otherwise(null))
      .withColumn("isNull", when(col(columnName).isNull, true).otherwise(null))
      .agg(
        max(col(columnName)).as("max"),
        count("isZero").as("is_zero"),
        count("isNull").as("is_null"),
        min(col(columnName)).as("min"),
        avg(col(columnName)).as("avg"),
        stddev(col(columnName)).as("std_dev")
      )
      .withColumn("col_name", lit(columnName))
  }

    def profileNumericColumns(df: DataFrame): DataFrame = {
      df.columns.filter(
        Set("DecimalType", "IntegerType", "LongType", "DoubleType", "FloatType", "ShortType")
          contains df.schema(_).dataType.toString
      )
        .map(getNumericColumnProfile(df, _))
        .reduce(_ union _)
        .toDF
        .select("col_name",
          "col_type",
          "is_null",
          "is_zero",
          "min",
          "max",
          "avg",
          "std_dev")
    }