私は次のようなデータフレームを持っています:
ID Notes
2345 Checked by John
2398 Verified by Stacy
3983 Double Checked on 2/23/17 by Marsha
たとえば、John、Stacy、またはMarshaの3人の従業員しかチェックしないとします。次のような新しい列を作成したいと思います。
ID Notes Employee
2345 Checked by John John
2398 Verified by Stacy Stacy
3983 Double Checked on 2/23/17 by Marsha Marsha
ここで正規表現またはgrepの方が良いですか?どのような機能を試すべきですか?ありがとう!
編集:私はたくさんの解決策を試してきましたが、何もうまくいかないようです。あきらめて、代わりに各従業員の列をバイナリ値で作成する必要がありますか? IE:
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
regexp_extract(col('Notes'), '(.)(by)(\s+)(\w+)', 4))
この式は、employee name from any positionを抽出しますby then スペーステキスト列(
col('Notes')
)
サンプルデータフレームを作成する
_data = [('2345', 'Checked by John'),
('2398', 'Verified by Stacy'),
('2328', 'Verified by Srinivas than some random text'),
('3983', 'Double Checked on 2/23/17 by Marsha')]
df = sc.parallelize(data).toDF(['ID', 'Notes'])
df.show()
+----+--------------------+
| ID| Notes|
+----+--------------------+
|2345| Checked by John|
|2398| Verified by Stacy|
|2328|Verified by Srini...|
|3983|Double Checked on...|
+----+--------------------+
_
必要なインポートを行う
_from pyspark.sql.functions import regexp_extract, col
_
df
で、regexp_extract(column_name, regex, group_number)
を使用して列からEmployee
名を抽出します。
ここでregex('(.)(by)(\s+)(\w+)'
)は
およびgroup_numberは4です。これは、グループ_(\w+)
_が式の4番目の位置にあるためです。
_result = df.withColumn('Employee', regexp_extract(col('Notes'), '(.)(by)(\s+)(\w+)', 4))
result.show()
+----+--------------------+--------+
| ID| Notes|Employee|
+----+--------------------+--------+
|2345| Checked by John| John|
|2398| Verified by Stacy| Stacy|
|2328|Verified by Srini...|Srinivas|
|3983|Double Checked on...| Marsha|
+----+--------------------+--------+
_
regexp_extract(col('Notes'), '.by\s+(\w+)', 1))
はかなりクリーンなバージョンのようです 使用中の正規表現を確認してください
by
以外のWordが名前の前にある他のサンプルが存在する場合、OPはより多くのサンプルをポストする必要がありますが、最も単純な形式で、提供された例に従って、この回答で十分です。
正規表現
^(\w+)[ \t]*(.*\bby[ \t]+(\w+)[ \t]*.*)$
交換
\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
注:上記の出力では、各列がタブ\t
文字で区切られているため、肉眼では正しく見えない場合がありますが、オンラインの正規表現パーサーを使用し、\t
を正規表現一致セクションに挿入するだけで、各列の開始/終了位置が表示されます。
^
行の先頭の位置をアサート(\w+)
1つ以上のWord文字(a-zA-Z0-9_
)をグループ1にキャプチャします[ \t]*
任意の数のスペースまたはタブ文字と一致します([ \t]
は、PCREなどの一部の正規表現フレーバーで\h
に置き換えることができます)(.*\bby[ \t]+(\w+)[ \t]*.*)
次をグループ2 にキャプチャします。.*
任意の文字に一致します(s
修飾子が使用されない限り改行を除く)\bby
単語の境界に一致\b
に続いてby
がそのまま続く[ \t]+
1つ以上のスペースまたはタブ文字に一致(\w+)
1つ以上のWord文字(a-zA-Z0-9_
)をグループ3にキャプチャします[ \t]*
任意の数のスペースまたはタブ文字に一致.*
任意の文字と何度でも一致$
行末の位置をアサート\1
最初のキャプチャグループで最後に一致したものと同じテキストに一致します\t
タブ文字\1
2番目のキャプチャグループで最後に一致したものと同じテキストに一致します\t
タブ文字\1
3番目のキャプチャグループで最後に一致したものと同じテキストに一致しますこのような何かが動作するはずです
import org.Apache.spark.sql.functions._
dataFrame.withColumn("Employee", substring_index(col("Notes"), "\t", 2))
正規表現を使用して適切な値を抽出する場合は、次のようなものが必要です
dataFrame.withColumn("Employee", regexp_extract(col("Notes"), 'regex', <groupId>)
私が質問をもう一度読んだとき、OPは従業員の固定リストについて話すかもしれません(「たとえば、人の従業員のみ確認するにはジョン、ステイシー、またはマーシャがある」)。これが実際に既知のリストである場合、最も簡単な方法は、Wordの境界を持つこの名前のリストに対してチェックすることです。
regexp_extract(col('Notes'), '\b(John|Stacy|Marsha)\b', 1)