#scala #apache-spark-sql #emoticons
#scala #apache-spark-sql #смайлики
Вопрос:
Привет stackoverflowers,
Не могли бы вы помочь взглянуть на то, как заменить смайлик в scala dataframe?
import spark.implicits._
val df = Seq(
(8, "bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️"),
(64, "bb")
).toDF("number", "word")
df.show(false)
------ -----------------------
|number|word |
------ -----------------------
|8 |bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️|
|64 |bb |
------ -----------------------
df.select($"word", regexp_replace($"word", "[^u0000-uFFFF]", "").alias("word_revised")).show(false)
----------------------- ---------------
|word |word_revised |
----------------------- ---------------
|bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️|bat★ ⛱ ✨♂️⛷❤️|
|bb |bb |
----------------------- ---------------
Ожидаемый результат
----------------------- ---------------
|word |word_revised |
----------------------- ---------------
|bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️|bat|
|bb |bb |
----------------------- ---------------
Большое спасибо за вашу помощь, @fonkap. Мне очень жаль, что цепочка подключилась к потоку так поздно, поскольку за последний месяц я получил еще одну историю спринта. Я хотел бы сказать, что опубликованный вами подход почти хорошо работает для смайлика. Но в моих исходных данных из нашего восходящего потока есть какой-то ненормальный значок. Есть ли у вас какие-либо предложения о том, как заменить их
scala> val df = Seq(
| (8, "♥♥♥♥♥☆ Condo֎۩ᴥ★Ąrt Ħouse Ŀocation")
| ).toDF("airPlaneId", "airPlaneName")
df: org.apache.spark.sql.DataFrame = [airPlaneId: int, airPlaneName: string]
scala> df.select($"airPlaneId", $"airPlaneName", regexp_replace($"airPlaneName", "[^u0000-u20CF]", "").alias("airPlaneName_revised")).show(false)
---------- ----------------------------------- ----------------------------
|airPlaneId|airPlaneName |airPlaneName_revised |
---------- ----------------------------------- ----------------------------
|8 |♥♥♥♥♥☆ Condo֎۞۩ᴥ★Ąrt Ħouse Ŀocation| Condo֎۞۩ᴥĄrt Ħouse Ŀocation|
---------- ----------------------------------- ----------------------------
Похоже, что какой-то символ по-прежнему остается неожиданным, помеченным как подчеркивание
Спасибо, что поделились, @mck. И предполагаемый новый подход выполним. В любом случае, происходит нежелательная замена.
scala> df.selectExpr(
| "airPlaneId",
| "airPlaneName",
| "replace(decode(encode(airPlaneName, 'ascii'), 'ascii'), '?', '?') airPlaneName_revised"
| ).show(false)
---------- ------------ --------------------
|airPlaneId|airPlaneName|airPlaneName_revised|
---------- ------------ --------------------
|8 |la Cité |la Cit? |
|9 |Aéroport |A?roport |
|10 |München |M?nchen |
|11 |la Tête |la T?te |
|12 |Sarrià |Sarri? |
---------- ------------ --------------------
Просто интересно, есть ли у нас какой-либо усовершенствованный подход, позволяющий исключить допустимый ascii, обрабатывать только смайлики или символы, пожалуйста?
Ответ №1:
regexp_replace
делает это правильно. Просто некоторые из «символов», которые вы написали, действительно находятся в u0000-uFFFF
интервале.
Доказательство:
import java.io.File
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
object Emoticon {
def main(args: Array[String]) {
val str = "bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️"
val bw = Files.newBufferedWriter(new File("emoji.txt").toPath, StandardCharsets.UTF_8)
bw.write(str)
bw.newLine()
val cps = str.codePoints().toArray
cps.foreach(cp => {
bw.write(String.format(" 0xx", cp.asInstanceOf[Object]))
bw.write(" - ")
bw.write(new java.lang.StringBuilder().appendCodePoint(cp).toString)
bw.newLine()
})
bw.close()
}
}
Открыть emoji.txt с помощью вашего браузера, и вы увидите:
(Стоит отметить, что некоторые символы являются комбинациями)
«Отфильтрованная» строка выглядит следующим образом:
Итак, все выглядит правильно!
Наконец, отвечая на ваш вопрос, вы можете использовать более узкий интервал символов, например: [^u0000-u20CF]
, и вы получите ожидаемый результат.
object Emoticon2 {
def main(args: Array[String]) {
val spark = SparkSession.builder.master("local[2]").appName("Simple Application").getOrCreate()
import spark.implicits._
val df = Seq(
(8, "bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️"),
(64, "bb")
).toDF("number", "word")
df.show(false)
df.select($"word", regexp_replace($"word", "[^u0000-u20CF]", "").alias("word_revised")).show(false)
}
}
выведет:
----------------------- ------------
|word |word_revised|
----------------------- ------------
|bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️|bat |
|bb |bb |
----------------------- ------------
Взгляните на: https://jrgraphix.net/research/unicode_blocks.php
Ответ №2:
Вы можете удалить все символы, отличные от ASCII, как показано ниже:
val df = Seq(
(8, "bat★😂 😆 ⛱ ✨🚣♂️⛷🏂❤️"),
(64, "bb")
).toDF("number", "word")
val df2 = df.selectExpr(
"number",
"replace(decode(encode(word, 'ascii'), 'ascii'), '?', '') word_revised"
)
df2.show(false)
------ ------------
|number|word_revised|
------ ------------
|8 |bat |
|64 |bb |
------ ------------
val df = Seq((8, "♥♥♥♥♥☆ Condo֎۩ᴥ★")).toDF("airPlaneId", "airPlaneName")
val df2 = df.selectExpr(
"airPlaneId",
"replace(decode(encode(airPlaneName, 'ascii'), 'ascii'), '?', '') airPlaneName_revised"
)
df2.show(false)
---------- --------------------
|airPlaneId|airPlaneName_revised|
---------- --------------------
|8 | Condo |
---------- --------------------