#scala #apache-spark #apache-spark-sql
Вопрос:
У меня есть фрейм данных со столбцом StringType ssn
, который называется следующим содержимым:
--------- | ssn| --------- |986-69-2371| |957305210| |965741549| |996118261| |946899347| |974393395| |998771903| |949429820| |983662042| |923785843| |948-84-1328| |971-48-1142| |972-79-2371| |989498321| |943129824| |976849729| |949-79-5213| |924761199| |991718011| |988-25-4619| ---------
Как вы можете видеть, содержимое неоднородно. Мое намерение состоит в том, чтобы отформатировать содержимое так, чтобы все строки имели одинаковый формат (формат, который я хочу xxx-xx-xxxx
). Все строки имеют 9 номеров. Я сделал это со следующей функцией:
df.withColumn("ssnFormat", when(col("ssn").contains("-"), col("ssn")).otherwise(format_string("%s-%s-%s", col("ssn").substr(1, 3), col("ssn").substr(4, 2), col("ssn").substr(6, 4))))
Мне было интересно, могу ли я сделать это таким образом, чтобы в выражении формата я указывал символы, которые я хочу взять из строки?
Вот что я имею в виду:
format_string("<-,-L", col("ssn"))
В предыдущей инструкции я намеревался выбрать первые символы строки, затем написать дефис, 2 следующих символа, дефис, а затем остальные символы.
Я хочу выяснить, возможен ли такой способ, потому что мне не очень нравится тот факт, что я должен выполнять подстроку тех частей, которые я хочу.
Ответ №1:
Вместо этого вы можете использовать regexp_replace
функцию, захватив группы xxx-xx-xxxx
и заменив их $1-$2-$3
:
val df1 = df.withColumn( "ssn", regexp_replace(col("ssn"), "^(\d{3})-?(\d{2})-?(\d{4})$", "$1-$2-$3") ) df1.show // ----------- //| ssn| // ----------- //|986-69-2371| //|957-30-5210| //|965-74-1549| //|996-11-8261| //|946-89-9347| //|974-39-3395| //|998-77-1903| //|949-42-9820| //|983-66-2042| //|923-78-5843| //|948-84-1328| //|971-48-1142| //|972-79-2371| //|989-49-8321| //|943-12-9824| //|976-84-9729| //|949-79-5213| //|924-76-1199| //|991-71-8011| //|988-25-4619| // -----------
Ответ №2:
Я думаю, я знаю, что вы имеете в виду, аналогично пользовательским форматам Excel. Один из способов состоит overlay
в том, чтобы вставить тире в нужную точку. Это похоже на функцию SQL STUFF
. Мне все еще приходится использовать regexp_replace
, чтобы убедиться, что строки находятся в согласованном формате до изменения, так что это не так элегантно:
df.select($"ssn", overlay( overlay( regexp_replace($"ssn", "-", ""), lit("-"), lit(4), lit(0)), lit("-"), lit(7), lit(0)). alias("formatted_ssn")).show
Мои результаты (из записной книжки Synapse, язык Scala):
Я думаю, что пример @blackbishop более элегантен и получил одобрение от меня. Я просто хотел записать рабочий пример overlay
и сказать: «Я знаю, что вы имеете в виду, и вот как это может выглядеть в Scala, и есть более простые способы сделать это». Я также смотрел patch
, но не мог заставить его работать с фреймом данных.