Как я могу использовать каждое слово, разделенное некоторыми символами, в Pyspark?

В настоящее время я работаю с Pyspark и столкнулся с, казалось бы, простой проблемой.

Я хочу сделать заглавной первую букву каждого слова, даже если слова разделены символами в следующем списке:

delimiter_list = [' ', '(', '+', '/', '-']

На самом деле initcap работает только для слов, разделенных пробелами.

Есть ли эффективное решение? Вот несколько примеров ввода-вывода:

input output
baden-baden Baden-Baden
markranstadt/brandenburg-kirchmöser Markranstadt/Brandenburg-Kirchmöser
ostrow mazowiecki/bialystok Ostrow Mazowiecki/Bialystok

person Leon Zajchowski    schedule 18.02.2021    source источник


Ответы (2)


Поскольку разделитель отличается, вы можете сначала добавить общий разделитель, скажем, # после каждого символа в вашем списке delimiter_list, используя regexp_replace:

regexp_replace(words, '(\\s|\\(|\\+|-|\\/)(.)', '$1#$2')

Теперь вы можете разделить на # и преобразовать полученный массив, начав каждый элемент с заглавной буквы, используя функцию transform. Наконец, соедините элементы массива, чтобы получить исходную строку, используя функцию array_join:

from pyspark.sql import functions as F

df1 = df.withColumn(
    "words_capitalized",
    F.expr(r"""
        array_join(
            transform(
                split(regexp_replace(words, '(\\s|\\(|\\+|-|\\/)(.)', '$1#$2'), '#'),
                x -> initcap(x)
            ),
            ""
        )
    """)
)

df1.show(truncate=False)

#+-----------------------------------+-----------------------------------+
#|words                              |words_capitalized                  |
#+-----------------------------------+-----------------------------------+
#|baden-baden                        |Baden-Baden                        |
#|markranstadt/brandenburg-kirchmöser|Markranstadt/Brandenburg-Kirchmöser|
#|ostrow mazowiecki/bialystok        |Ostrow Mazowiecki/Bialystok        |
#+-----------------------------------+-----------------------------------+
person blackbishop    schedule 18.02.2021

Я думаю, что UDF может понадобиться. Возможно, вам придется вручную настроить шаблон регулярного выражения из-за необходимости экранировать определенные специальные символы, такие как ( и +.

import pyspark.sql.functions as F
import re

df.show(truncate=False)
+-----------------------------------+
|words                              |
+-----------------------------------+
|baden-baden                        |
|markranstadt/brandenburg-kirchmöser|
|ostrow mazowiecki/bialystok        |
+-----------------------------------+


words_udf = F.udf(
    lambda w: re.sub(r'(^| |\(|\+|-|/)([a-z])', lambda x: x.group(1) + x.group(2).upper(), w)
)

df.select(words_udf('words').alias('words')).show(truncate=False)
+-----------------------------------+
|words                              |
+-----------------------------------+
|Baden-Baden                        |
|Markranstadt/Brandenburg-Kirchmöser|
|Ostrow Mazowiecki/Bialystok        |
+-----------------------------------+
person mck    schedule 18.02.2021