通过 udf 进行拼写校正
spark spelling correction via 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
简单的情况(前两个例子)可以通过
很好地处理
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))
但我不确定如何以良好且可概括的方式处理 UDF 中更复杂/链接的条件替换。
如果它只是一个相当小的拼写列表 < 50,你会建议在 UDF 中对它们进行硬编码吗?
您可以使 UDF 接收多列:
val spellingCorrection2= udf((x: String, y: String) => if (x=="conditionC" && y=="conditionD") "replacementC" else x)
val misspellings3 = misspellings1.withColumn("B", spellingCorrection2($"B", $"C")
为了使其更加通用,您可以使用从两个条件的元组到字符串的映射,与第一种情况相同。
如果您想进一步概括它,则可以使用数据集映射。基本上创建一个包含相关列的案例 class,然后使用 as 将数据框转换为案例 class 的数据集。然后使用数据集映射,并在其中对输入数据使用模式匹配来生成相关校正并转换回数据帧。
这应该更容易编写,但会产生性能成本。
现在我将使用以下似乎工作得很好并且更容易理解的方法:https://gist.github.com/rchukh/84ac39310b384abedb89c299b24b9306
如果 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:_*)
我需要使用 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
简单的情况(前两个例子)可以通过
很好地处理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))
但我不确定如何以良好且可概括的方式处理 UDF 中更复杂/链接的条件替换。 如果它只是一个相当小的拼写列表 < 50,你会建议在 UDF 中对它们进行硬编码吗?
您可以使 UDF 接收多列:
val spellingCorrection2= udf((x: String, y: String) => if (x=="conditionC" && y=="conditionD") "replacementC" else x)
val misspellings3 = misspellings1.withColumn("B", spellingCorrection2($"B", $"C")
为了使其更加通用,您可以使用从两个条件的元组到字符串的映射,与第一种情况相同。
如果您想进一步概括它,则可以使用数据集映射。基本上创建一个包含相关列的案例 class,然后使用 as 将数据框转换为案例 class 的数据集。然后使用数据集映射,并在其中对输入数据使用模式匹配来生成相关校正并转换回数据帧。 这应该更容易编写,但会产生性能成本。
现在我将使用以下似乎工作得很好并且更容易理解的方法:https://gist.github.com/rchukh/84ac39310b384abedb89c299b24b9306
如果 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:_*)