Как заменить смайлик на пустую строку в scala dataframe?

#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              |
 ---------- --------------------