web-dev-qa-db-fra.com

PySpark - Correspondance de chaîne pour créer une nouvelle colonne

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
7
Ashley O

Bref

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.


Code

Voir le code utilisé ici

Regex

^(\w+)[ \t]*(.*\bby[ \t]+(\w+)[ \t]*.*)$

Remplacement

\1\t\2\t\3

Résultats

Contribution

2345          Checked by John
2398          Verified by Stacy
3983          Double Checked on 2/23/17 by Marsha 

Sortie

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.


Explication

Regex

  • ^ 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

Remplacement

  • \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 capture
1
ctwheels

Quelque 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>)
0

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)
0
Matschek