【分散処理】PySpark ~ CSV / White Spaceの扱い ~

■ はじめに

https://dk521123.hatenablog.com/entry/2019/11/24/225534
https://dk521123.hatenablog.com/entry/2020/07/09/000832
https://dk521123.hatenablog.com/entry/2020/11/23/224349
https://dk521123.hatenablog.com/entry/2020/07/30/195226

の続き。

 PySpark で、CSVファイルとして書き込む際に
White Space (ホワイトスペース; 半角SP、タブ etc) が
勝手に削除されてしまう現象に見舞われたので
White Spaceの扱いについて、調べてみた

目次

【1】ホワイトスペースに関するプロパティ
 1)書き込み - write
  a)ignoreLeadingWhiteSpace
  b)ignoreTrailingWhiteSpace
 2)読み込み - read
  a)ignoreLeadingWhiteSpace
  b)ignoreTrailingWhiteSpace

【2】サンプル
 例1:書き込み時の挙動
 例2:読み込み時の挙動

【1】ホワイトスペースに関するプロパティ

ホワイトスペースに関して read/write で、
以下の2つのプロパティが用意されている。
~~~~~~~~~~
a)ignoreLeadingWhiteSpace
b)ignoreTrailingWhiteSpace
~~~~~~~~~~

使用上の注意

[1] 「1)書き込み - write」と「2)読み込み - read」で
  デフォルト値が異なることに注意
[2] 個人的には、プロパティ名と挙動が分かりづらい
[3] 読み込み時は、囲み文字で囲まれている値の前後のホワイトスペースは
 True/Falseに関わらず維持される(トリムされずにそのまま)

1)書き込み - write

https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrameWriter.csv.html

a)ignoreLeadingWhiteSpace

* 前の White Space を書き込むかどうか(default : True)
 => True : 前の White Space を無視して、そのまま書き込む
 => False : 前の White Space をトリムする

API仕様より抜粋
ignoreLeadingWhiteSpacestr or bool, optional
a flag indicating whether or not leading whitespaces
 from values being written should be skipped.
If None is set, it uses the default value, true.

=> このプロパティ名だったら
 True にしたら、white spaceを無視して書き込みにいく
 って意味に見える
(実際には、FalseでWhite Spaceが書き込まれる)

b)ignoreTrailingWhiteSpace

* 後ろの White Space を書き込むかどうか(default : True)
 => True : 後ろの White Space を無視して、そのまま書き込む
 => False : 後ろの White Space をトリムする

ignoreTrailingWhiteSpacestr or bool, optional
a flag indicating whether or not trailing whitespaces
 from values being written should be skipped.
If None is set, it uses the default value, true.

2)読み込み - read

https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrameReader.csv.html

a)ignoreLeadingWhiteSpace

* 前の White Space を読み込むかどうか(default : False)
 => True : 前の White Space をトリムして読み込む(White Spaceを削除)
 => False : 前の White Space をトリムせずにそのまま読み込む

API仕様より抜粋
ignoreLeadingWhiteSpacestr or bool, optional
A flag indicating whether or not leading whitespaces
 from values being read should be skipped.
If None is set, it uses the default value, false.

b)ignoreTrailingWhiteSpace

* 後ろの White Space を読み込むかどうか(default : False)
 => True : 後ろの White Space をトリムして読み込む(White Spaceを削除)
 => False : 後ろの White Space をトリムせずにそのまま読み込む

API仕様より抜粋
ignoreTrailingWhiteSpacestr or bool, optional
A flag indicating whether or not trailing whitespaces
 from values being read should be skipped.
If None is set, it uses the default value, false.

【2】サンプル

例1:書き込み時の挙動

from pyspark import SparkContext
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType
from pyspark.sql.types import StructField
from pyspark.sql.types import StringType


spark_context = SparkContext()
spark = SparkSession(spark_context)

# 前後に半角SPを入れてある
rdd = spark_context.parallelize([
  (' x0001 ', '  Mike  ', '  Sales  '),
  (' x0002 ', '  Tom  ', '  IT  '),
  (' x0003 ', '  Sam  ', '  Sales  '),
  (' x0004 ', '  Kevin  ', '  Human resources  '),
  (' x0005 ', '  Bob  ', '  IT  '),
  (' x0006 ', '  Alice  ', '  Banking  '),
  (' x0007 ', '  Carol  ', '  IT  '),
])
schema = StructType([
  StructField('id', StringType(), False),
  StructField('name', StringType(), False),
  StructField('job', StringType(), False),
])

data_frame = spark.createDataFrame(rdd, schema)

# まず表示させてみる
data_frame.show()

# 実験1:Falseを指定 (White Spaceをそのまま出力)
data_frame.write \
  .mode('overwrite') \
  .csv('./out_false',
    sep=",",
    header=True,
    ignoreLeadingWhiteSpace=False,
    ignoreTrailingWhiteSpace=False)

# 実験2:Trueを指定 (White Spaceをトリムする)
data_frame.write \
  .mode('overwrite') \
  .csv('./out_true',
    sep=",",
    header=True,
    ignoreLeadingWhiteSpace=True,
    ignoreTrailingWhiteSpace=True)

# 実験3:指定しない (White Spaceをトリムする)
data_frame.write \
  .mode('overwrite') \
  .csv('./out_none',
    sep=",",
    header=True)

出力結果

+-------+---------+-------------------+
|     id|     name|                job|
+-------+---------+-------------------+
| x0001 |   Mike  |            Sales  |
| x0002 |    Tom  |               IT  |
| x0003 |    Sam  |            Sales  |
| x0004 |  Kevin  |  Human resources  |
| x0005 |    Bob  |               IT  |
| x0006 |  Alice  |          Banking  |
| x0007 |  Carol  |               IT  |
+-------+---------+-------------------+

実験1:出力結果ファイル(Falseの場合:前後がトリムされていない)

id,name,job
 x0001 ,  Mike  ,  Sales  

実験2:出力結果ファイル(Trueの場合:前後がトリムされている)

id,name,job
x0001,Mike,Sales

実験3:出力結果ファイル(指定しない場合:前後がトリムされている)

id,name,job
x0001,Mike,Sales

例1:書き込み時の挙動

from pyspark import SparkContext
from pyspark.sql import SparkSession

spark_context = SparkContext()
spark = SparkSession(spark_context)

print("実験1:Falseを指定")
data_frame = spark.read.csv(
  "input.csv",
  header=True,
  ignoreLeadingWhiteSpace=False,
  ignoreTrailingWhiteSpace=False)
data_frame.show(truncate=False, vertical=True)

print("実験2:Trueを指定")
data_frame = spark.read.csv(
  "input.csv",
  header=True,
  ignoreLeadingWhiteSpace=True,
  ignoreTrailingWhiteSpace=True)
data_frame.show(truncate=False, vertical=True)

print("実験3:指定しない")
data_frame = spark.read.csv(
  "input.csv",
  header=True)
data_frame.show(truncate=False, vertical=True)

入力ファイル「input.csv

    id,name,job
x0001 ,  Mike  ,  Sales  
  x0002   ,   Tom  ,   IT  
   x0003 ,  Sam  , Sales  
" x0004 ","    Kevin    ","   Human resources  "
"x0005",  "Mike"  ,  "IT"  
  "   x0006   "  ,  "  Alice   "," Banking    "
"   x0007" ,"     Carol    "," IT  "    

出力結果

実験1:Falseを指定
-RECORD 0----------------------
     id | x0001
 name   |   Mike
 job    |   Sales
-RECORD 1----------------------
     id |   x0002
 name   |    Tom
 job    |    IT
-RECORD 2----------------------
     id |    x0003
 name   |   Sam
 job    |  Sales
-RECORD 3----------------------
     id |  x0004
 name   |     Kevin
 job    |    Human resources
-RECORD 4----------------------
     id | x0005
 name   |   "Mike"
 job    |   "IT"
-RECORD 5----------------------
     id |   "   x0006   "
 name   |   "  Alice   "
 job    |  Banking
-RECORD 6----------------------
     id |    x0007
 name   |      Carol
 job    |  IT

実験2:Trueを指定
-RECORD 0--------------------
 id   | x0001
 name | Mike
 job  | Sales
-RECORD 1--------------------
 id   | x0002
 name | Tom
 job  | IT
-RECORD 2--------------------
 id   | x0003
 name | Sam
 job  | Sales
-RECORD 3--------------------
 id   |  x0004
 name |     Kevin
 job  |    Human resources
-RECORD 4--------------------
 id   | x0005
 name | Mike
 job  | IT
-RECORD 5--------------------
 id   |    x0006
 name |   Alice
 job  |  Banking
-RECORD 6--------------------
 id   |    x0007
 name |      Carol
 job  |  IT

実験3:指定しない
-RECORD 0----------------------
     id | x0001
 name   |   Mike
 job    |   Sales
-RECORD 1----------------------
     id |   x0002
 name   |    Tom
 job    |    IT
-RECORD 2----------------------
     id |    x0003
 name   |   Sam
 job    |  Sales
-RECORD 3----------------------
     id |  x0004
 name   |     Kevin
 job    |    Human resources
-RECORD 4----------------------
     id | x0005
 name   |   "Mike"
 job    |   "IT"
-RECORD 5----------------------
     id |   "   x0006   "
 name   |   "  Alice   "
 job    |  Banking
-RECORD 6----------------------
     id |    x0007
 name   |      Carol
 job    |  IT

関連記事

PySpark ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2019/11/14/221126
PySpark ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2021/04/03/004254
PySpark ~ CSV / 基本編 ~
https://dk521123.hatenablog.com/entry/2019/11/24/225534
PySpark ~ CSV / Read/Writeのプロパティ ~
https://dk521123.hatenablog.com/entry/2020/07/30/195226
PySpark ~ CSV / escape ~
https://dk521123.hatenablog.com/entry/2020/11/23/224349

【AWS】AWS Data Wrangler ~ 入門編 ~

■ はじめに

AWS Data Wrangler ってのがあるようなので調べてみた。

目次

【1】AWS Data Wrangler
 0)公式ドキュメント
 1)AWS Data Wranglerとは?
【2】環境設定
 1)pip / conda
 2)AWS Glue
 3)その他AWSサービス

【1】AWS Data Wrangler

0)公式ドキュメント

https://aws.amazon.com/jp/blogs/news/how-to-use-aws-data-wrangler/
Github
https://github.com/awslabs/aws-data-wrangler
APIリファレンス
https://aws-data-wrangler.readthedocs.io/en/2.7.0/api.html

1)AWS Data Wranglerとは?

https://aws.amazon.com/jp/blogs/news/launch-aws-data-wrangler-v1-0/

より抜粋
~~~~~~~~~~~~~~~
Data Wranglerは
Pandasライブラリの機能をAWSに拡張するオープンソースの
Pythonライブラリです。
~~~~~~~~~~~~~~~
 => 便利Pythonツールみたいな感じ?
 => 内容をみるとboto3 API をラップしたようなメソッド(※)もあるので
  ETL以外のAWS処理全般で使えそう。

※ 例えば、以下のAPI仕様にある「awswrangler.s3.delete_objects」など

https://aws-data-wrangler.readthedocs.io/en/2.7.0/stubs/awswrangler.s3.delete_objects.html#awswrangler.s3.delete_objects

import awswrangler as wr

# Delete both objects
wr.s3.delete_objects(['s3://bucket/key0', 's3://bucket/key1'])

# Delete all objects under the received prefix
wr.s3.delete_objects('s3://bucket/prefix')

Data Wrangler って名前について

cf. Wrangler (ラングラー) = 口論者、乗用馬の世話係、カウボーイ etc...

 => 馬や牛を集めて操るカウボーイ(wrangler)のように、
  データを自在に操る「Data Wrangler」っていう言葉があるらしい

https://www.oreilly.co.jp/books/9784873117942/

【2】環境設定

1)pip / conda

https://aws-data-wrangler.readthedocs.io/en/2.7.0/install.html

# pip
pip install awswrangler

# conda
conda install -c conda-forge awswrangler

2)AWS Glue

PySpark Jobs(Ver2.0) の場合
https://aws-data-wrangler.readthedocs.io/en/2.7.0/install.html#aws-glue-pyspark-jobs

より意訳

[1] 対象のGlue PySpark jobのJobパラメータを以下のように指定する

 * Key: --additional-python-modules
 * Value: pyarrow==2,awswrangler

 ※ Versionを特定したい場合、pyarrow==2,awswrangler==2.7.0

それ以外のJob(Python shell)の場合
https://aws-data-wrangler.readthedocs.io/en/2.7.0/install.html#aws-glue-python-shell-jobs

より意訳

[1] 以下からwheel ファイル(.whl)をダウンロードする

https://github.com/awslabs/aws-data-wrangler/releases

[2] S3上にwheel ファイルを置く
[3] 対象のGlue Jobの Python library path に[2]のファイルパスを指定する.

3)その他AWSサービス

* 以下に記載されているので、こちらを参照。

https://aws-data-wrangler.readthedocs.io/en/2.7.0/install.html

参考文献

https://ayemos.hatenablog.jp/entry/2019/10/04/111753
https://blog.serverworks.co.jp/tech/2019/10/08/aws-data-wrangler-tutorial/
https://sadayoshi-tada.hatenablog.com/entry/2020/06/12/080000

コンピュータサイエンス(CS) ~ 修士 / Master ~

■ はじめに

https://dk521123.hatenablog.com/entry/2021/02/28/000000

の続き。

今回は、コンピュータサイエンス (Computer Science; CS) の
大学院 (Master) 編。

目次

【1】個人的な条件
【2】調べた際に分からなかった英単語
【3】ジョージア工科大学

【1】個人的な条件

* オンライン - Online
* コンピュータサイエンス修士課程 - Computer Science Masters
* 低予算
* 海外

【2】調べた際に分からなかった英単語

* Postgraduate = 大学院

【3】ジョージア工科大学

* Georgia Tech’s online Master of Science in Computer Science
 (OMS CS) 
* 授業だけなら入学しなくても、
 udacity(ユダシティ)のサイトで会員登録すれば(ある程度?)受講可能

https://www.udacity.com/

* 入学は、春・秋(自由にいつでもって訳じゃない)

1)必要事項

https://omscs.gatech.edu/program-info/application-deadlines-process-requirements

2)English Proficiency

https://catalog.gatech.edu/admissions/grad/english-proficiency-intl-students/

English Proficiency Qualification Minimum Score Required
TOEFL 577 (paper based), 90 (Internet based)
IELTS 6.5 Reading/Listening/Speaking, 5.5 Writing

3)Current Courses

https://omscs.gatech.edu/current-courses

参考文献

https://ja.takp.me/posts/how-i-was-accepted-to-georgia-tech-omscs/
https://kevins-blog.com/online-master-degree-cs-georgia-tech/
https://zenn.dev/empitsu88/articles/d7e96ce9480b830a52e8
動画
https://www.youtube.com/watch?v=1aQkPqh0FBY

関連記事

コンピュータサイエンス(CS) ~ 学士 / Bachelor ~
https://dk521123.hatenablog.com/entry/2021/02/28/000000