ステージ1: Python演習の補足 (情報工学実験 3 : データマイニング班)
- サンプルスクリプト: Download
- インタプリタ/スクリプト
- 数学関数
- リスト型の基本、関数
- フロー制御
- 文字列処理・操作
- File I/O
- 2〜3週間での目標
- 言語処理100本ノックの第1セット、第2セット程度を記述できるレベルを目指す。最低目標は「どのように書けそうか」を説明でき、一部の部品について具体的に調べながら記述できること。
- 進め方
- Pythonのプログラミング能力は少しずつ向上してば十分。これまでに学んだC/Javaと比べてどの点に注意すべきかを学びつつ、基本的なノウハウとして四則演算、リスト型、フロー制御、関数、クラス、文字列処理を部分的に身につけるを当面の目標とする。他要素については適宜その都度調べながら書けるようになろう。
Pythonならではの特徴
- 変数は動的に型付けされる。
例えば適当な変数を用意して数字/文字列/リスト等を保存した後で、その変数の型を type() で確認してみよう。
- インデントとスコープが連動している。
例えばC言語のfor文においてどこからどこまでを繰り返すかは{}で区切られるが、Pythonではインデントで指定する。関数のスコープ、クラスのスコープも同様。
- switch/case文が無い。
開発者の方針で存在しません。if ... elif ... elif ...で代用。
- スクリプト実行時とモジュールロード時とで異なる動作を記述できる。
例えばmaintest.pyをダウンロードし、(1)ターミナル上からスクリプトとして実行した場合、(2)Pythonインタプリタを起動し、"import maintest"として読み込んだ場合とで動作結果(print出力結果)を比較しよう。これを利用することのメリットとして、例えばユニットテスト自体を同じファイル内に記述することができる。
Tips
- インタプリタ(対話モード)でのタブ機能による補完
環境構築でやっているはずのrlcompleterを設定してあると、インタプリタ内でタブによる補完機能が利用できます。これは、例えばクラス変数のように「いくつかの関数や変数を有するオブジェクト」のような変数に対して「クラス変数名.」まで記入した時点でタブキーを押すと、どのような関数/変数が用意されているかを確認することができます。
- オブジェクトや関数についてのヘルプ: help()
インタプリタで「help(変数/関数/クラス)」を実行すると、そのオブジェクトに関するヘルプ文(正確にはpydocで記述されたドキュメント)を参照することができます。
機能別演習課題
以下は基本的なコードを書けるかどうかを判断するための課題例です。言語処理100本ノックの第1セット、第2セットでも構いません。- インタプリタ/スクリプト
- 参考:公式チュートリアル2節
- 課題例1-1: スクリプトの実行。
hello.pyをダウンロードし、スクリプトとして実行せよ。
- 課題例1-2: インタプリタの実行。
Pythonインタプリタ(対話モード)を起動し、hello.pyと同じ処理を実行せよ。
- 数学関数: 四則演算, 絶対値fabs(), 自然対数log(), N乗pow(), 平方根sqrt(), 正弦sin(), 余弦cos(), 正接tan()等
- 参考: 数学関数mathモジュール
- リスト型の基本: スライス, len(), enumerate()
- 参考: 公式チュートリアル3.2.14
- 課題例3-1: リストの基本。
2次元空間(x,y)における任意の点をリスト型で2点分が与えられたとする。例えば point1 = [0,1], point2 = [1,2] 。
このとき、(1) point1 のx座標、y座標を個別に出力せよ(各リストは2個の要素で構成されている。これを1つずつ要素を指定して出力しよう)。また、(2) point1 のリスト内要素数を出力せよ。
- 課題例3-2: 距離の算出。
上記 point1, point2 を元に、2点間のユークリッド距離を求めよ。
- 課題例3: リスト型変数へのアイテム追加。
上記 point1, point2 を3次元空間へと拡張したい。point1=[0,1,2], point2=[1,2,3]となるように追加せよ。
- フロー制御: if, for, while, 関数: def
- 参考: 公式チュートリアル4節
- 以下は@nakarx/ieリストから収集したツイートをTSVで保存した、~/datasets/Tweets*.tsv を参照しながら進めるものとする。
Quiz: 上記ファイルはどうやったら取得できる?
- 課題例4-1: リストのループ処理。
あるユーザのツイート履歴(ツイートID(自然数), ユーザID(自然数), ツイート日時(文字列:%Y-%m-%d %H:%M:%S+09), スクリーン名(文字列), ツイート本文(文字列))をリストとして用意したとする。例えば tweet = [389745333770518529, 61726083, 'naltoma', '2013-06-11 12:02:17+09', '雑炊で痛いというのは胃腸か何か分からないけど相当酷いことになってそうな。。子供の頃絶食断食やった時は終わった後の「水」ですら痛かったのは覚えてるけど、そういうものとも違うだろうしなぁ。'] 。このリストから次のように出力するプログラムを書け。
(出力例) ツイートID: 389745333770518529 ユーザID: 61726083 ツイート日時: 2013-06-11 12:02:17+09 スクリーン名: naltoma ツイート本文: 雑炊で痛いというのは胃腸か何か分からないけど相当酷いことになってそうな。。子供の頃絶食断食やった時は終わった後の「水」ですら痛かったのは覚えてるけど、そういうものとも違うだろうしなぁ。
- 課題例4-2: 関数の利用。
課題例4-1で動作させたコードを、関数として作成せよ。ただし、以下の条件を守ること。
ファイル名: exp4-2.py 関数名: format_tweet(tweet) 引数: tweet: 課題例4-1におけるtweetそのもの。 戻り値: 出力用に整形したstring型変数(課題例4-1と同じ出力を行う)。 # 利用時の流れ >>> string = format_tweet(tweet) >>> print string ツイートID: 389745333770518529 ユーザID: 61726083 ツイート日時: 2013-06-11 12:02:17+09 スクリーン名: naltoma ツイート本文: 雑炊で痛いというのは胃腸か何か分からないけど相当酷いことになってそうな。。子供の頃絶食断食やった時は終わった後の「水」ですら痛かったのは覚えてるけど、そういうものとも違うだろうしなぁ。
- 課題例4-3: ユニットテスト
- 課題例4-4:
課題例4-1のようなツイート履歴が多数集まったリスト tweets が下記のように与えられたとする。
tweets = [[tweet0], [tweet1], [tweet2]] # ここで、上記の [tweet0] は、課題例4-1におけるリストと同じ型だとする。 # つまり、[tweet0]の中には5項目のアイテムが保存されている。 # 具体的なデータセットを用意するため、以下の手順で用意しよう。 # (1) shark:~/datasets/Tweets-*.tsv の最新版を取得。 # (2) mod100.py(テキストファイルからmod行単位で抽出するプログラム)をダウンロード。 # (3) (1),(2)を同じディレクトリに保存し、下記コマンドで小規模なデータセットを作成。 ./mod100.py Tweets-(略).tsv 1000 > 1000.tsv # (4) 上記で作成した 1000.tsv に含まれる冒頭11行について、 # 手動で tweets = [[tweet0],~,[tweet9]] として保存せよ。
このtweetsに対し、(a)ツイート履歴が何件のがあるか、(b)1件のツイート履歴に含まれている要素数は何件か、(c)複数回ツイートしているユーザについてその合計ツイート数はいくらか、を各々プログラムで求めよ。
- 課題例4-5: mod100.pyの解読。
mod100.pyを読み、どのような手続きで何を実現しているかを解読せよ。
- 文字列処理・操作: len(), +連結, 改行等削除strip(), 正規表現re, 置換, マッチング vs 検索
- File I/O: csv/tsvファイル読み込み, pickle
- 課題例6-1: TSVファイルの読み込み。
課題例4-2における tweets を作成する途中段階で 1000.tsv を作成した。このファイルの冒頭11行のみを読み込み、tweets として保存せよ(tweetsを再現せよ)。ここでは「1ツイート=1リスト」で構わない(辞書型を用いる必要は無い)。注意点として、(a)1行目の「tweet_id」から始まる行はコメント行のため保存する必要は無い。(2)ツイートIDとユーザIDは数(自然数/整数)として保存すること。
- 課題例6-2: パターンマッチング。
(1) 前述 tweets の「ツイート日時」は半角スペースを区切りと看做した時、前半が年月日、後半が時間になっている。一日単位のツイート履歴数(件数)を抽出せよ。
(2) 「ツイート日時」後半の時間に注目し、ツイートをAM(午前)とPM(午後)に分類せよ。ここでは0時から11時までをAM、12時から23時までをPMとして判定するだけで良い。また、文字列からdatetime型に変更するにはdatetime.strptime()が利用できる。(datetimeを使わない方法でも構わない)
- 課題例6-3: pickleによるオブジェクトのファイル出力&読み込み。
(1) 前述 tweets をpickleを用いてファイル tweets.txt に書き出せ。
(2) (一度close()した後で)書き出した tweets.txt を開き、pickleを用いて tweets 変数にロードし直せ。
- 課題例6-1: TSVファイルの読み込み。
- 関数
- import
- 課題例8: スクリプト実行とimport時の違い。
課題例6-1(TSVファイルの読み込み)を関数化せよ。この際、以下の条件を満たすこと。
ファイル名: exp8.py 関数名: read_tweettsv 引数: ファイル名(1000.tsvを引数で指定するものとする) *既存のプログラムではファイル名を直接指定しているため、 引数で指定されたファイルを開くように修正すること。 戻り値: tweets # 動作確認用の print 出力は、スクリプト実行時のみ動作するように # (__name__ == __main__ の時のみ動作するように)修正せよ。
上記のように修正した exp8.py を元に、(1) スクリプトとして動作させた場合と、(2)import した時の動作、を各々確認し、違いを述べよ。また、動作が異なる理由について検討せよ。 - 課題例8-1: Pythonスクリプトのファイル名について。
exp8.py を複製し、新しいファイル「exp8-1.py」を作成せよ。複製したexp8-1.pyに対し、前述と同様に(1),(2)の動作を確認せよ。その結果、(2)は正しく動作しないはずである。どのようなエラーが出力されるか確認し、その理由を考えよ。また、このことからファイル名についての制限を検討せよ。
- 以下、準備中。
- 課題例8: スクリプト実行とimport時の違い。
- クラス
- 辞書型の基本: keys(), values(), iteritems()