如何将Scala Spark Dataset.show重定向到log4j记录器

13

Spark API文档展示了如何从数据集或数据框发送到标准输出的位置获取漂亮的打印片段。

这个输出是否可以定向到log4j记录器?或者,有人能分享创建类似于df.show()格式化输出的代码吗?

是否有一种方法可以在将.show()输出推送到记录器之前和之后都允许stdout进入控制台?

http://spark.apache.org/docs/latest/sql-programming-guide.htm

val df = spark.read.json("examples/src/main/resources/people.json")

// Displays the content of the DataFrame to stdout
df.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

你可以随时实现类似的功能:https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/Dataset.scala#L247 - T. Gawęda
那让我到达了。谢谢。 - teserecter
1
对于Java,请参见https://dev59.com/hmoy5IYBdhLWcg3wMLSj,了解如何将控制台输出重定向到字符串。 - user3730028
您可以通过反射在此处查看如何使用内部的showString函数:https://dev59.com/Jazla4cB1Zd3GeqPA7bg - Double Sept
2个回答

5

showString()函数来自teserecter,源码在Spark的Dataset.scala文件中。

你不能直接在你的代码中使用该函数,因为它是包私有的,但你可以将以下代码片段放在一个名为DatasetShims.scala的文件中,并在你的类中混入该特质以访问该函数。

package org.apache.spark.sql

trait DatasetShims {
  implicit class DatasetHelper[T](ds: Dataset[T]) {
    def toShowString(numRows: Int = 20, truncate: Int = 20, vertical: Boolean = false): String =
      "\n" + ds.showString(numRows, truncate, vertical)
  }
}

2
将此实用方法放在您的代码中的某个位置,以生成带有dataframe.show()格式的格式化字符串。
然后只需将其包含在日志输出中,例如: log.info("此时名为df的数据框显示为:\n"+showString(df,100,-40))
/**
    * Compose the string representing rows for output
    *
    * @param _numRows Number of rows to show
    * @param truncate If set to more than 0, truncates strings to `truncate` characters and
    *                   all cells will be aligned right.
    */
    def showString(
        df:DataFrame
        ,_numRows: Int = 20
        ,truncateWidth: Int = 20
    ): String = {
        val numRows = _numRows.max(0)
        val takeResult = df.take(numRows + 1)
        val hasMoreData = takeResult.length > numRows
        val data = takeResult.take(numRows)

        // For array values, replace Seq and Array with square brackets
        // For cells that are beyond `truncate` characters, replace it with the
        // first `truncate-3` and "..."
        val rows: Seq[Seq[String]] = df.schema.fieldNames.toSeq +: data.map { row =>
            row.toSeq.map { cell =>
            val str = cell match {
                case null => "null"
                case binary: Array[Byte] => binary.map("%02X".format(_)).mkString("[", " ", "]")
                case array: Array[_] => array.mkString("[", ", ", "]")
                case seq: Seq[_] => seq.mkString("[", ", ", "]")
                case _ => cell.toString
            }
            if (truncateWidth > 0 && str.length > truncateWidth) {
                // do not show ellipses for strings shorter than 4 characters.
                if (truncateWidth < 4) str.substring(0, truncateWidth)
                else str.substring(0, truncateWidth - 3) + "..."
            } else {
                str
            }
        }: Seq[String]
    }

我认为答案至少缺少一个花括号,但我认为它没有作为字符串检索,并且变量名为rows的连接缺失。 - Double Sept

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接