J'ai une quantité insensée de colonnes de chemin à diviser en 2 colonnes, basename et dirname. Je sais comment obtenir facilement le nom de base de mes chemins en utilisant:
+------------------------------+--------------------------+ |column1 |dirname | +------------------------------+--------------------------+ |/test/coucou/jambon/hello/file|/test/coucou/jambon/hello | |/test/jambon/test |/test/jambon | +------------------------------+--------------------------+
Cependant, je me démène pour obtenir le nom du répertoire comme ceci:
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 | +------------------------------+---------+
J'ai essayé différentes solutions mais je ne parviens pas à trouver une solution fonctionnelle en colonne.
Ma meilleure idée serait de soustraire $ "basename"
à $ "column1"
, mais je n'ai pas trouvé de moyen de soustraire String dans Spark.
3 Réponses :
Vous pouvez utiliser expr pour sous-chaîne la colonne1. Le code devrait ressembler à celui ci-dessous. J'espère que cela vous sera utile.
//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 | +------------------------------+--------+-------------------------+
semble intéressant, même si j'aurais aimé que ce soit un moyen plus simple: D C'est trop compliqué pour l'OMI, quelque chose qui devrait être beaucoup plus facile ... Merci beaucoup pour votre aide.
Eh bien, après y avoir mis plus de pensées. cela semble être le seul moyen de gérer un chemin court tel que /filex.txt
en gardant le dernier /
(supprimez le -1 dans la sous-chaîne)
Une autre approche consisterait à utiliser des 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 | +------------------------------+--------+-------------------------+
ne fonctionne pas lorsque vous utilisez un chemin plus court tel que: /file.txt le chemin de la colonne est vide et devrait être IMO
Approche alternative à une solution déjà fournie utilisant l'expression régulière
Obtenez votre expression régulière correctement. regexp_extract UDF vous donnera ce que vous vouliez.
df.withColumn("path",regexp_extract($"column1", "^(.+)(/.+)$", 1 ) ) )
Sortie
+------------------------------+--------------------------+--------+ |column1 |path |fileName| +------------------------------+--------------------------+--------+ |/test/coucou/jambon/hello/file|/test/coucou/jambon/hello/|file | |/test/jambon/prout/test |/test/jambon/prout/ |test | +------------------------------+--------------------------+--------+
Modifier:
Sans slash, les expressions régulières sont plus faciles à gérer:
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)
ne fonctionne pas lorsque vous utilisez un chemin plus court tel que: /file.txt
le chemin de la colonne est vide et doit être IMO a /