J'ai un dataframe comme:
ID Notes
2345 Checked by John
2398 Verified by Stacy
3983 Double Checked on 2/23/17 by Marsha
Disons par exemple qu'il n'y a que 3 employés à vérifier: John, Stacy ou Marsha. Je voudrais faire une nouvelle colonne comme suit:
ID Notes Employee
2345 Checked by John John
2398 Verified by Stacy Stacy
3983 Double Checked on 2/23/17 by Marsha Marsha
Est-ce que regex ou grep est meilleur ici? Quel type de fonction devrais-je essayer? Merci!
EDIT: J'ai essayé un tas de solutions, mais rien ne semble fonctionner. Devrais-je abandonner et créer des colonnes pour chaque employé, avec une valeur binaire? C'EST À DIRE:
ID Notes John Stacy Marsha
2345 Checked by John 1 0 0
2398 Verified by Stacy 0 1 0
3983 Double Checked on 2/23/17 by Marsha 0 0 1
Dans sa forme la plus simple, et selon l'exemple fourni, cette réponse devrait suffire, même si le PO devrait envoyer plus d'échantillons s'il existe d'autres exemples où le nom doit être précédé d'un mot autre que by
.
Regex
^(\w+)[ \t]*(.*\bby[ \t]+(\w+)[ \t]*.*)$
Remplacement
\1\t\2\t\3
2345 Checked by John
2398 Verified by Stacy
3983 Double Checked on 2/23/17 by Marsha
2345 Checked by John John
2398 Verified by Stacy Stacy
3983 Double Checked on 2/23/17 by Marsha Marsha
Remarque: La sortie ci-dessus sépare chaque colonne par le caractère de tabulation \t
. Elle peut donc ne pas sembler être exacte à l'œil nu. Utiliser simplement un analyseur de regex en ligne et insérer \t
dans la section de correspondance des regex devrait vous montrer où chaque colonne commence/se termine.
^
Assert la position au début de la ligne(\w+)
Capturez un ou plusieurs caractères Word (a-zA-Z0-9_
) dans le groupe 1[ \t]*
Correspond à n'importe quel nombre d'espaces ou de caractères de tabulation ([ \t]
peut être remplacé par \h
dans certaines versions de regex telles que PCRE)(.*\bby[ \t]+(\w+)[ \t]*.*)
Capturez les éléments suivants dans le groupe 2 .*
Correspond à n'importe quel caractère (sauf la nouvelle ligne sauf si le modificateur s
est utilisé)\bby
Correspond à une limite de mot \b
, suivie de by
littéralement[ \t]+
Correspond à un ou plusieurs espaces ou caractères de tabulation(\w+)
Capturez un ou plusieurs caractères Word (a-zA-Z0-9_
) dans le groupe 3[ \t]*
Correspond à n'importe quel nombre d'espaces ou de tabulations.*
Correspond à n'importe quel caractère n'importe quel nombre de fois$
Assert la position à la fin de la ligne\1
Correspond au même texte que le dernier apparié par le premier groupe de capture\t
caractère de tabulation\1
Correspond au même texte que le dernier apparié par le 2e groupe de capture\t
caractère de tabulation\1
Correspond au même texte que le dernier apparié par le 3ème groupe de captureQuelque chose comme ça devrait marcher
import org.Apache.spark.sql.functions._
dataFrame.withColumn("Employee", substring_index(col("Notes"), "\t", 2))
Si vous voulez utiliser regex pour extraire la valeur appropriée, vous avez besoin de quelque chose comme:
dataFrame.withColumn("Employee", regexp_extract(col("Notes"), 'regex', <groupId>)
Lorsque je relis la question, le PO peut parler d'une liste fixe d'employés ("Disons par exemple qu'il n'y a que 3 employés vérifier: John, Stacy ou Marsha") vraiment une liste connue, le moyen le plus simple est de vérifier cette liste de noms avec des limites de Word:
regexp_extract(col('Notes'), '\b(John|Stacy|Marsha)\b', 1)