通过udf激发拼写错误

时间:2016-11-21 22:03:17

标签: apache-spark apache-spark-sql user-defined-functions spark-dataframe udf

我需要使用spark纠正一些拼写。 不幸的是像

这样的天真的方法
val misspellings3 = misspellings1
    .withColumn("A", when('A === "error1", "replacement1").otherwise('A))
    .withColumn("A", when('A === "error1", "replacement1").otherwise('A))
    .withColumn("B", when(('B === "conditionC") and ('D === condition3), "replacementC").otherwise('B))

不适用于spark How to add new columns based on conditions (without facing JaninoRuntimeException or OutOfMemoryError)?

简单的案例(前两个例子)可以通过

很好地处理
val spellingMistakes = Map(
    "error1" -> "fix1"
  )

  val spellingNameCorrection: (String => String) = (t: String) => {
    titles.get(t) match {
      case Some(tt) => tt // correct spelling
      case None => t // keep original
    }
  }
  val spellingUDF = udf(spellingNameCorrection)

  val misspellings1 = hiddenSeasonalities
    .withColumn("A", spellingUDF('A))

但我不确定如何在一个优秀的& amp;中处理UDF中更复杂/链式的条件替换。一般化的方式。 如果它只是一个相当小的拼写列表<您会建议在UDF中对它们进行硬编码吗?

3 个答案:

答案 0 :(得分:0)

您可以让UDF接收多个列:

val spellingCorrection2= udf((x: String, y: String) => if (x=="conditionC" && y=="conditionD") "replacementC" else x)
val misspellings3 = misspellings1.withColumn("B", spellingCorrection2($"B", $"C")

为了使这更加通用化,您可以使用两个条件的元组中的映射到与第一个案例相同的字符串。

如果您想进一步概括它,那么您可以使用数据集映射。基本上使用相关列创建一个case类,然后使用as将数据帧转换为case类的数据集。然后使用数据集映射并在其中使用输入数据上的模式匹配来生成相关更正并转换回数据帧。 这应该更容易编写,但会有性能成本。

答案 1 :(得分:0)

现在我将使用以下内容,这似乎工作得很好并且更容易理解:https://gist.github.com/rchukh/84ac39310b384abedb89c299b24b9306

答案 2 :(得分:0)

如果spellingMap是包含正确拼写的地图,则df是数据帧。

val df: DataFrame = _ 
val spellingMap = Map.empty[String, String] //fill it up yourself
val columnsWithSpellingMistakes = List("abc", "def")

像这样写一个UDF

def spellingCorrectionUDF(spellingMap:Map[String, String]) =
udf[(String), Row]((value: Row) =>
{
  val cellValue = value.getString(0)
  if(spellingMap.contains(cellValue)) spellingMap(cellValue)
  else cellValue
})

最后,你可以将它们称为

val newColumns = df.columns.map{
case columnName =>
  if(columnsWithSpellingMistakes.contains(columnName)) spellingCorrectionUDF(spellingMap)(Column(columnName)).as(columnName)
  else Column(columnName)
}
df.select(newColumns:_*)