C言語プログラマがPythonのお勉強で気になったことメモ(その1)

データサイエンティストを目指すべく、Pythonを学習することにしました。

Pythonはturtleでちょっと遊んだことがあるくらいで、ほぼ初心者みたいなものです。
一時期tkinterで遊んでいた時期もありましたね、今思い出しました。

さてPythonの情報はWeb上にたくさんありまして、公式のチュートリアルドキュメントを読むだけでもある程度の文法はわかります。
docs.python.org

ただし、どうしても実践的な面に欠けるので、書籍を買って勉強することにしました。
今回購入したのは以下の本です。


環境構築

このテキストはJupyter NotebookあるいはGoogle Colaboratoryの使用を想定しています。
私は手っ取り早く使えるGoogle Colaboratoryでコーディングすることにしました。

1章で気になったこと

とりあえず1章に掲載されているコードを順番に写経してみました。
テーブル管理とか、応用情報技術者試験の勉強で触ったこともないSQL文法をやったのを思い出します。

ひとまず、気になって調べたことをつらつらと書いていきます。まぁメモなので。

asはライブラリを別名をつけて呼び出すための予約語

import pandas as pd
m_store = pd.read_csv('m_store.csv')

というのがありますが、pythonasは別名(エイリアス)をつけてライブラリを呼び出すための予約語のようです。
上の例でいえば、pandasというライブラリを呼び出し、それにpdという別名をつけているのです。
これは、このあとでいちいちpandasと書くのが面倒なので、その略記としてpdを使うのであって、
べつに別名をつけずに全部pandasと書いてもコードは動いてくれます。

import pandas
m_store = pandas.read_csv('m_store.csv')

注意しなくてはいけないのは、asは、ライブラリを呼び出してから別名をつけているのではなく、
別名をつけてライブラリを呼び出しているという点です。
なので、以下のコードはエラーになります。pdという名前でpandasを呼び出したので、この時点で使えるライブラリの名前はpdのみだからです。

import pandas as pd
m_store = pandas.read_csv('m_store.csv')

concatはconcatenateのこと

order_all = pd.concat([tbl_order_4, tbl_orer_5], ignore_index=True)

concatは英語で「連結」を意味する"concatenate"から来ています。
「コンケイトネイト」と読みたいですが、発音記号はkənkǽtənèitで、カタカナ的には「コンキャトネイト」です。

公式ドキュメントをみると、引数は最低限objsがあればOKなようです。

pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)

pandas.pydata.org

objsについては、

objs: a sequence or mapping of Series or DataFrame objects

と説明があり、SeriesorDataFrameの配列あるいはマッピングを入れなさい、とのことです。
先ほどの例でも、連結したい2つのDataFrameをリストにして[tbl_order_4, tbl_orer_5]の形で渡していますね。
(ちなみにpandas.read_csv()は読み込んだCSVファイルをDataFrame形式で返してくれるそうです。)

cwdはカレントワーキングディレクトリのこと

import os
current_dir = os.getcwd()
current_dir

で使われているos.getcwd()の"cwd"は"current working directory"の略のようです。
カレントディレクトリを指す言葉が、言語によってcdだったりcwdだったりするので、ホントはどちらかに統一してほしいですね。

「ユニオン」はconcat()、「ジョイン」はmerge()

データの結合を意味する言葉として「ユニオン」「ジョイン」の2つが出てきます。
これはSQLをはじめとするデータベースの用語です。
対応するpandasのメソッドはそれぞれconcat()merge()です。
ちなみに、ファイルパスを作成するところで

tbl_order_file = os.path.join(current_dir, 'tbl_order_*.csv')
tbl_order_file

join()が出てきますが、これはまた別のメソッドです。

globは「かたまり」という意味

import glob
tbl_order_files = glob.glob(tbl_order_file)
tbl_order_files

で出てくる"glob"は、英語で「かたまり」という意味だそうです。

glob.glob()について、公式ドキュメントには

Return a possibly-empty list of path names that match pathname, which must be a string containing a path specification.

とあるので、マッチするパスをリスト形式で出力してくれるようです。
マッチするパスがなければ、空のリストを返すようです。
docs.python.org

f''はフォーマット済み文字列リテラル

print(f'{file}:{len(order_data)}')

に出てくるf''Python 3.6で追加された新機能である「フォーマット済み文字列リテラル」、通称「f-string」だそうです。
実行時に{}の中を評価してくれるので、上記の例のように関数を入れることもできます。

DataFrameの行・列を指定して取得する方法

order_all['total_amount'].describe()

を実行することで、キーが'total_amount'の列を取得し、それのdescribe()を出力してくれます。

ところで列の取得はキーを指定すればいいようなのですが、行の取得はどうすればいいのでしょうか?
どうやさスライスを[]に入れてあげると、行のインデックスと認識してくれるそうです。

order_all[0:1]

を実行することで、インデックス0の行を出力してくれます。
(スライスm:nは「m以上n未満の整数」という意味ですから、0:1は0のみを指します。)

スライスでなければ行のインデックスと認識されないので、以下のコードはエラーになります。

order_all[0]

locはlocationのこと

order_data = order_all.loc[order_all['store_id'] != 999]

によって、列'store_id'999ではない行すべてを抽出しています。
ここで使われているloc[]は"location"のことです。

DataFrame.loc[]は、最後が[]で終わっています。
実はDataFrame.loc[]はメソッドではなくプロパティであり、
[]で終わっていることからわかるとおり、リスト形式のプロパティです。
今回は2次元のリスト(配列)になります。

2次元のリストに対して、数字を1つ渡すと行の指定になります。

order_all.loc[0]

とすると、インデックスが0の行が出力されます。

order_all.loc[0:2]

とすると、インデックスが0~2の行、あわせて3行が出力されます。
(あれ?なんでなんだ?)

数字を2つ渡すと、1つ目の引数が行を、2つ目の引数が列を指定します。

order_all.loc[:5, 'order_id']

と書くと、インデックスが0~5までの6行のうち、列のキーが'order_id'のものが出力されます。

列だけを指定したい場合は、以下のようにすればOKです。

order_all.loc[:, 'order_id']

先ほどの

order_data = order_all.loc[order_all['store_id'] != 999]

の例に戻ると、これは[]の中に,がありませんから、行だけを指定しています。
そして、行の指定方法として、order_all['store_id'] != 999が書かれています。

order_all['store_id'] != 999は一体なんなのかというと、
order_all['store_id']で抽出した列の各要素に対して、999と一致しないかどうかをTrueFalseのリストで返すというものです。

出力はこんな感じ。
f:id:stacked-tip:20211230105259p:plain

これをloc[]に入れると、Trueの行だけ、つまり、999と一致しなかった行だけを返すことになります。

また、loc[]に存在しない行・列を入力することで、行・列を新規に追加することもできます。

order_data.loc[order_data['takeout_flag']==0, 'takeout_name'] = 'デリバリー'
order_data.loc[order_data['takeout_flag']==1, 'takeout_name'] = 'お持ち帰り'

のところとかがそうですね。



続きです。
stacked-tip.hateblo.jp