Spark: UDF, чтобы получить имя от пути - PullRequest
2 голосов
/ 03 апреля 2019

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

val df = Seq("/test/coucou/jambon/hello/file"
    ,"/test/jambon/test")
    .toDF("column1")
df.withColumn("basename", substring_index($"column1"  , "/", -1))
.show(2, false)
+------------------------------+---------+
|column1                       |basename |
+------------------------------+---------+
|/test/coucou/jambon/hello/file|file     |
|/test/jambon/test             |test     |
+------------------------------+---------+

Однако я изо всех сил пытаюсь получить вот такое имя:

+------------------------------+--------------------------+
|column1                       |dirname                   |
+------------------------------+--------------------------+
|/test/coucou/jambon/hello/file|/test/coucou/jambon/hello |
|/test/jambon/test             |/test/jambon              |
+------------------------------+--------------------------+

Я пробовал различные решения, однако яЯ не могу найти функциональное столбчатое решение.
Моя лучшая идея - вычесть $"basename" до $"column1", однако я не смог найти способ вычесть строку в Spark.

Ответы [ 3 ]

4 голосов
/ 03 апреля 2019

Альтернативный подход к уже предоставленному решению с использованием регулярного выражения

Получите правильное регулярное выражение. regexp_extract UDF даст вам то, что вы хотели.

   val df = Seq("/test/coucou/jambon/hello/file"
      , "/test/jambon/prout/test")
      .toDF("column1")

    import org.apache.spark.sql.functions.regexp_extract

    df.withColumn("path", regexp_extract('column1, "^\\/(\\w+\\/)+", 0)).withColumn("fileName",regexp_extract('column1, "\\w+$", 0)).show(false)

Вывод

+------------------------------+--------------------------+--------+
|column1                       |path                      |fileName|
+------------------------------+--------------------------+--------+
|/test/coucou/jambon/hello/file|/test/coucou/jambon/hello/|file    |
|/test/jambon/prout/test       |/test/jambon/prout/       |test    |
+------------------------------+--------------------------+--------+

Редактировать:
Без косой черты с регулярным выражением проще управлять:

df.withColumn("path",regexp_extract($"column1", "^(.+)(/.+)$", 1 ) ) )
3 голосов
/ 03 апреля 2019

Вы можете использовать expr для подстроки column1. Код должен выглядеть следующим образом. Я надеюсь, что это полезно.

//Creating Test Data
val df = Seq("/test/coucou/jambon/hello/file"
  ,"/test/jambon/prout/test")
  .toDF("column1")

val test = df.withColumn("basename", substring_index($"column1"  , "/", -1))
    .withColumn("path", expr("substring(column1, 1, length(column1)-length(basename)-1)"))

test.show(false)
+------------------------------+--------+-------------------------+
|column1                       |basename|path                     |
+------------------------------+--------+-------------------------+
|/test/coucou/jambon/hello/file|file    |/test/coucou/jambon/hello|
|/test/jambon/prout/test       |test    |/test/jambon/prout       |
+------------------------------+--------+-------------------------+
2 голосов
/ 03 апреля 2019

Другой подход заключается в использовании UDF:

import org.apache.spark.sql.functions.udf

val pathUDF = udf((s: String) => s.substring(0, s.lastIndexOf("/")))

val test = df.withColumn("basename", substring_index($"column1"  , "/", -1))
    .withColumn("path", pathUDF($"column1"))

test.show(false)
+------------------------------+--------+-------------------------+
|column1                       |basename|path                     |
+------------------------------+--------+-------------------------+
|/test/coucou/jambon/hello/file|file    |/test/coucou/jambon/hello|
|/test/jambon/prout/test       |test    |/test/jambon/prout       |
+------------------------------+--------+-------------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...