在宅リーマン勉強日誌

忘れがちな毎日のメモ。

【7日目】KaggleでPythonの勉強してみた【独学】

KaggleのコースでPythonの勉強をしています。 コースも後半に入ってきてとうとうペースが落ち始めました…。

当初は7日くらいで全部終わらせたいと思っていましたが、まだまだ残っています。 ひえ~

勉強内容

Lesson:Strings and Dictionaries (Tutorial)

勉強時間:50分

Lesson:Strings and Dictionaries (Tutorial)

勉強時間

TutorialはCourseの和訳(概略)、Tutorialは試行とどう考えていたかを記しています。

Lesson:Strings and Dictionaries(Tutorial)

Strings

Pythonの文字列の扱いは、他の言語とは違う特徴的な部分です。

本章では、文字列のメソッドと定義されているオペレーションを解説します。 このような文字列のパターンは、文書形のデータサイエンス業務にしばしば現れ、Pythonの特徴ともなっています。

String syntax

これまでのレッスンで、もうすでにたくさんの文字列例を見てきました。 ''""で囲われているものです。 ''""の中で同じ記号で文章を表したいときはバックスラッシュを使うことでエラーを回避することができます。 f:id:KashiwaMOCHI:20200501112016p:plain Pythonの改行は\nだけでなく、docstringを書く際の”””で囲うことで普通の改行でも改行として扱うことができます。 print()は書くたびに自動的に改行を挿入します。 改行がいらない場合はend=""を挿入しましょう。

Strings are sequences

文字列は文字の連続として考えられます。 なのでリストに入れることが可能なのです。

主に違うところは不変であることです。 途中の文字を変更したり、.appendを使用することはできません。

String methods

リストと同じように文字列はたくさんの役に立つメソッドを持っています。

<例>

  • .upperですべての文字を大文字に変更可能

  • .lowerですべての文字を小文字に変更可能

  • .indexで文字列の検索が可能

  • .startswithで指定した文字列で始まるかどうか(True/False)

  • .endswithで指定した文字列で終わるかどうか(True/False)

  • .splitで文を空白毎に区切り、分割したもののそれぞれをリストのエレメントとする。空白以外で区切る場合は.split('/')のように指定する(例:2020/4/1→["2020","4","1"])

  • .joinで複数の変数の文字をつなげる。また、「何でつなげるか」を指定できる。(例:'/'.join(["2020","4","1"])でsplitしたものを元に戻せる)

  • で二つの変数の文字列をつなげることができる。間に文字列以外の型式を入れたいときは、必ず文字列にしてからつなげること。

  • 文字の統合が複数あったりするときは.formatを使うこと。これだと型式をあまり気にする必要がない。"{}, you'll always be the {}th planet to me.".format(planet, position)

formatはかなり便利で、{}内にいろいろ指定できる。

例えば{:.2%}で小数点以下2桁に%を付ける、と指定できる。 また、何度も繰り返し使う言葉は、format()内をリストのように扱って、{0}みたいに指定することができる。

Dictionaries

辞書(ディクショナリ)はPythonに備えられた、値のキーマップとなるものです。 単語の読み替えとかを書き記しておくことで、使える辞書リストが作成できています。 numbers = {'one':1, 'two':2, 'three':3}で指定。

  • 呼び出し:numbers['one']
  • 書き込み:numbers['eleven'] = 11

また、in演算子でその単語がディクショナリに含まれているかを返してくれます。

  • .values().keys()でそれぞれのバリューまたはキーを返します。バリューがキーに紐づく値。

  • .item()を使用すると、辞書のキーと値を同時に反復処理することができます。

さらにディクショナリの機能を知りたい場合はhelp(dict)を実行しましょう

Lesson:Strings and Dictionaries(Exercise)

Q0:ウォームアップ

それぞれの文字列の長さを求める問題がいくつか。 これそれぞれ後々使いそうだから、見てみると

a=""の長さ 答え:0

b = "it's ok"の長さ答え:7(空白や記号もカウントされることに注意!)

c = 'it\'s ok'の長さ答え:7(実際に印字されないものはカウントされない)

d = """hey"""の長さ答え:3(上記と同じく、印字されないものはカウントされない)

e = '\n'の長さ答え:1(改行は2文字で構成されていても1文字として扱われる)

Q1:関数を完成せよ(米国の郵便番号)

データサイエンティストはデータをきれいにするのに80%、その処理に文句を言うのに20%の時間を費やしているといわれています。 アメリカの郵便番号データをきれいにする関数を書いてみましょう。文字列に対して、有効な郵便番号かどうかを返してください。ここでの有効な郵便番号とは、5桁の数字で表されている文字列のことです。

ヒント:strはここで使えるメソッドを持っているので、help(str)で確認してみましょう。

これまでのメソッドではできないってことですが、一旦len()だけでやったらどうなるのかを確認します。

def is_valid_zip(zip_code):
    """Returns whether the input string is a valid (5 digit) zip code
    """
    return len(zip_code)==5

結果:不正解

Expected return value of False given zip_code='1234x', but got True instead.

1234xを入れると、Falseにならないといけないのに、Trueが返ってきちゃうよ~という答えです。 なので、列の長さ以外で、「これらはすべて数字である」か「型が混合していない」メソッドを探してくる必要がありますね。

私は大層真面目なので、きちんとhelp(str)を読んで探してきました。(ググるのが下手すぎて、見つからなかっただけ)

そこで目を付けたのが、str.isdecimal()str.isdigit()の二つでした。 実際に'1234x'を入れてみるとFalseが返ってきたので、入れてみるとうまくとおりました。 どちらでも正解だったのですが、この二つ、挙動が同じようで、何が違うのか説明を見てもいまいちわかりませんでした。 (ちなみに正解例はisdigit)

ここの違いは下記ブログで丁寧に検証されていました。 kk6.hateblo.jp

まだ一問目か…。

Q2:関数を完成せよ(ニュース内のキーワード)

ある研究者は何千ものニュース記事を集めてきました。しかし、彼女はある特定の単語を含んだ記事に注目したいです。関数を完成させて、記事のリストをフィルタリングしてください。

あなたの関数は下記基準を満たしている必要があります。

  • キーワードが他の単語の中に含まれるものであってはなりません。(例)closedを検索の際にenclosedもヒットさせてしまう
  • 大文字小文字にかかわらずヒットさせましょう。
  • ドットやカンマを無視してキーワードをヒットさせてください。(例)~~~ closed.の場合、ドットを無視してclosedとしてヒットさせてください。
def word_search(doc_list, keyword):
    """
    Takes a list of documents (each document is a string) and a keyword. 
    Returns list of the index values into the original list for all documents 
    containing the keyword.

    Example:
    doc_list = ["The Learn Python Challenge Casino.", "They bought a car", "Casinoville"]
    >>> word_search(doc_list, 'casino')
    >>> [0]
    """
    #データの前処理:小文字に統一
    keyword = keyword.lower()
    ans = []
    for i in range(len(doc_list)):
        doc_list[i] = doc_list[i].lower()
        if doc_list[i].find(keyword)>=0:
            temp = []
            temp = doc_list[i].split()
            for j in range(len(temp)):
                if temp[j].find(keyword)>=0:
                    if len(temp[j]) == len(keyword):
                        ans.append(i)
                        break
                    else:
                        if not(temp[j].isalpha()) and len(temp[j]) == len(keyword)+1:
                            ans.append(i)
                            break
    return ans

エラーに対して、直し続けて、めちゃくちゃダサい関数が爆誕しました。

正答例内に見たことがないメソッドがあったりするので、ここの確認はまた明日。

新出単語

manipulation:巧妙な扱い

perk:元気を取り戻す

immutable :不変の

respectively:それぞれの

concatenate:(~を)鎖状につなぐ

zip code:郵便番号

jargon:専門語

【6日目】KaggleでPythonの勉強してみた【独学】

KaggleのコースでPythonの勉強をしています。 前回までは毎日少しずつ進めていましたが、とうとう止まってしまいました。 遅れを取り戻すべく、できるだけ進めていきたいです。

勉強内容

Lesson:Loops and List Comprehensions (Exercise)

勉強時間:60分

TutorialはCourseの和訳(概略)、Tutorialは試行とどう考えていたかを記しています。

Lesson:Loops and List Comprehensions (Exercise)

Q1は一昨日終わらせたので、続きから。

Q2-a:[1, 2, 3, 4] > 2がどのように実行されるかを考えよ

Q2-b:RとPythonは二つのリストを比べ、正誤を返すライブラリと同じ挙動の関数を作成せよ

任意の数nよりも大きいエレメントかどうか(正誤)を返す関数を作りなさい。 Q2-aはエラーを出してしまうので、これができる関数をQ2-bで作りなさい、問題です。 最初思いついたのは、閾値より大きいと書き出しをするというもの

def elementwise_greater_than(L, thresh):
    """Return a list with the same length as L, where the value at index i is 
    True if L[i] is greater than thresh, and False otherwise.
    
    >>> elementwise_greater_than([1, 2, 3, 4], 2)
    [False, False, True, True]
    """
    return [ans for ans in L if ans>thresh]
print(elementwise_greater_than([1, 2, 3, 4], 2))

ただこれでは、[3,4]としか印字されないです。 ans>threshの時はTrueを返して、としたいけど、ifの中で返すのでは最終的なアウトプットが出せないのは前の問題の段階で自明。

挙動を確認するために、やはりいきなり1行で書くのはよくないですね。 複数回のエラーを経て、下記コードにたどり着きました。

def elementwise_greater_than(L, thresh):
    """Return a list with the same length as L, where the value at index i is 
    True if L[i] is greater than thresh, and False otherwise.
    
    >>> elementwise_greater_than([1, 2, 3, 4], 2)
    [False, False, True, True]
    """
    ans  =[]
    for judge in L:
        if judge >thresh:
            ans.append(True)
        else:
            ans.append(False)
    return ans

やはりまだPythonのリスト内条件文に慣れない…。 正答例と方向性は同じだけど、圧倒的にスマートでないことがばれるコードを書いているので、正答例をまねするように書くようにせねば。 瞬時にこれが思いつくようになるのにあとどれくらいかかるだろうか。

Q3:関数を完成させよ。

ある期間に提供された食事リストが与えられる。2日連続で提供された食事であればTrueを、それ以外はFalseを返す

この食事リストというものがわからないので、エラーを吐かせるためにいくつかコードを入れてみると、テストでは以下のリストが入ってくるみたい。

Falseの例:meals=['Egg', 'Spam']

Trueの例:meals=['Spam', 'Eggs', 'Spam', 'Spam', 'Bacon', 'Spam']

配列を返す、とかではなく、純粋にTrue, Falseを返せばいいからQ1が少し使えるかなと思いました。 ただ、一つ前の配列をどう入れるかがわからない。(Cとかだとi-1とか使うけど、ださいかなと思って却下。) return any([serve == meals for serve in meals]) この一行のmealsの部分を一つ前の内容が入るようにすればいいのですが…。

def menu_is_boring(meals):
    """Given a list of meals served over some period of time, return True if the
    same meal has ever been served two days in a row, and False otherwise.
    """
    past = ""
    for serve in meals: 
        if serve == past:
            return True
        past = serve
    return False  

なんかかっこよくしたかったけど…と思ったけど、正答例もあまり変わらず。 ダサいと思って却下したものが正答例だったのでこれはおっけー! ちょっとだけよくできました。(という気分)

Lesson:Loops and List Comprehensions (Exercise)

3日にわたって続けた

Q4:スロットマシンチャレンジestimate_average_slot_payout(難問)

スロット関数を動かすと、何ドル勝ったかが出ます。基本的には0が返ってきますが、時折多額が返ってきます。平均的にいくらの原因があるかはカジノで秘密とされていますが、モンテカルロ法という方法を使うことで、期待値=平均的な結果を出すことができます。以下の関数を完成させてスロットマシンの1プレイ当たりの期待値を計算してください。

これ、各セクションの難問でカジノ関係はいつぞやからか、Python Challenge Casinoって呼ばれてるみたい笑

あと聞きなれない「モンテカルロ法*1という言葉。(情報系の学生だと散々聞いてるかもしれないですが、近似の方ではなくギャンブルな方のやつです)

でもこれ読み進めていくと、モンテカルロ法使っているのかわからないんですよね~。なのでモンテカルロ法の詳細は脚注のページに任せるとして、関数自体は平均値ですね! シンプルにできますが、解が載っていないので、自分でやった例を書いておきます。

def estimate_average_slot_payout(n_runs):
    """Run the slot machine n_runs times and return the average net profit per run.
    Example calls (note that return value is nondeterministic!):
    >>> estimate_average_slot_payout(1)
    -1
    >>> estimate_average_slot_payout(1)
    0.5
    """
    sum_n = 0
    for i in range(n_runs):
        sum_n += play_slot_machine()
    return (sum_n-n_runs)/n_runs

他の回答例はリンク先へ。 著者のColin Morrisもコメントしていて、激熱ですね。 今回の問題はリスト内でやる方法ももちろんありますが、かなりの試行数を行うことでやっと平均的な0.025の値に近づいていくので、リストでメモリを食うよりもループの中で都度計算した方がよいとのこと。 www.kaggle.com

同じような回答だけど、解が全然違うという場合も多いと思います。 試行回数が足りない可能性があります。

ではどのくらい必要なんでしょうか。 f:id:KashiwaMOCHI:20200501091420p:plain

あくまで乱数の平均なので、試行回数が低い方は本当にあてにならない数値ではあるんですが、0.025に収束し始めるのが、試行回数が10の7乗を越したあたりに見えますね。100万回やれば、ようやく確実にプラスになるくらいです。全然勝てないですね。

しかも勝てたとしても、3円くらい笑 パチンコ業界が儲かるわけだ。

*1:モンテカルロ法とは、昔モナコモンテカルロのカジノで、この方法を使ってカジノをつぶしたといわれている方法です。(本当かな) 有効なゲームは、ブラックジャックバカラ・ルーレット、なので今回のスロットも一応近いっちゃ近いのかなー。スロットが有効なのかはわからん。www.xn--lck0a5auxk.jp

海外でロスバゲした【英語サンプル付き】

海外で初めてロスバゲ(=預入荷物が返却場所で流れてこない)を体験しました。

ちなみにこれは荷物がちゃんと帰ってくるタイプのロスバゲ向け記事です。

 

EU圏内でのトランジットの結果でしたが、自分の荷物が出てこないあの焦燥感は何にも代えられない。そして、その後も色んな事を検索しまくって、本当に時間を費やしました。

次困ったときに優雅に過ごせるようにメモを書きます。

ロスバゲが日本だともっと楽かもしれないけど、全て英語で対応しなければだったので、その時使った例文も書きます。英語で対応してもらっただけまだましだったかな~

最後に実体験も書いておくので参考まで。

f:id:KashiwaMOCHI:20200430143322p:plain



 

海外空港で自分の荷物が出てこなかったときに優雅に対応するには

手荷物受取のコンベアを丁寧に確認

基本的には、新しい荷物流れてこなくなったな…と思った時点で終わりだけど、しっかりもう自分の荷物が流れてこないことを確認する。


カウンターの方に助けを乞う

大きい空港で、わからなければ周りの職員の方に連れて行ってもらうと話を通してもらえるので楽。

"My bagage seems not come out. Where shoul I go?" (私の荷物が出てこない。どこに行けばいい?)マイ バゲジ シームス ノット カム アウト. ウェア シュド アイ ゴー

 

だけど、出口近くとかに大抵困ったときの受付があるので、てくてくそちらに向かうのでオッケー。荷物が出てこない、というと「本当に?念入りに確認した?もう一回見てきて」などと言われる(You sure?ユーシュアとかAgainアゲインと聞こえたらおそらくそう言われている)。

"I checked carefully."(念入りに確認した)アイ チェック(ド) ケアフリー

 "I wait over 3 rounds."(3周以上待った)アイ ウェイ(ト) オーバー スリーラウンド

とか言っておくと(実際待ってなくても)書類を渡されて下記を記入する。

  1. 現地の滞在場所
  2. メールアドレス
  3. 電話番号
  4. パスポートの情報

 などなど。

スーツケースの詳細も聞かれるので、写真があるといい。色や固さ(ソフト/ハード)などをイラストから選ぶスタイルなので、あまり英語ができなくてもいいかも。色はかなり細かいので、本当に写真を持っていればよかったーと思った。

いつ頃届けられる予定だ、だの、受取はどこがいいか(日本に送るか、滞在のホテルに送るか、空港で受け取るか)を聞かれる。

航空会社にもよるけど、最後に"日用品(トイレタリー)はいるか?"といわれるので、もらえるものはもらっておく笑 *詳細は体験記へ


ホテルのフロントで受取をお願いしておく

これは別にやらなくてもいいけど、

My luggage will come in few days. So if you received, please let me know.”(私の荷物が数日で届くから、届いたら教えてください)マイ ラゲジ ウィル カミン フュー デイズ. ソー イフ ユー レシーブ(ド) プリーズ レッミー ノー

荷物が届かないって正直すごくすごく不安に過ごすことになるので(私は3回聞きに行った)、一言添えておくとよいと思います。


周辺のドラッグストア・衣料品店を確認

すぐ荷物が届くのであればいいけど、時間がわからない場合はホテル周辺のドラッグストアや衣料品ですぐ必要なものを買う。

モントリオール条約で上限15万くらい補償してくれるので、旅行保険とかクレカで補償をつけていなくても全く問題ありません。

もちろん補償対象は決まっていて、すぐに必要な化粧品とか洋服のみです。

その場でしか使えない(ことになっている)化粧品類は全額、その後使えるものとして洋服等は半額バックしてくれます。

もちろん、買ったときのレシートはすべて取っておいてください。


航空会社へ請求

これは帰国後とか落ち着いてからゆっくりで大丈夫

航空会社に、上記の補償してもらえるものを買った領収書を送る。

「(航空会社名) 手荷物遅延」とかで調べると、どこから申請したらいいんだ、ってくらい何も見つからなかったので、普通に問い合わせ窓口からメールを送りました。

【実体験】どういう状況でロスバゲしたのか

さて、最後になぜロスバゲしたのか?結局荷物は戻ってきたのか?を書きたいと思います。

 

出発 

まず、航路ですが、欧州の某国からドイツ・フランクフルト経由でまた他の欧米某国でした。

欧州内なのに直行便がない、くらいにはあまりかかわりのない国から国への旅行でした。

 

航路:某欧米国→ドイツ・フランクフルト→某欧米国

 

今考えるとチェックインカウンターで、ダイレクトなのか経由なのかをそもそも聞かれませんでしたね…

ただ相手は天下のルフトハンザ便。しかもたまたま出張でビジネスクラスだったから、何にも疑問を抱かずに、いました。

 

到着。…ロスバゲ発覚 。

欧州域内(短時間)のビジネスクラスだと、乗客ってすごく少ないので、荷物預けている人も10人なんていないんですよ。(そもそも上限が12人くらい?)

 

だから、かなりベルトコンベヤから荷物が出てきてかなり早い段階でエコノミークラスの荷物も出てきて(タグが付いてないからわかる)、なんかおかしいな?と思いました。

 

到着は23時過ぎだったので、おそらく最後の到着便だったのでしょう。他の荷物はなく、ただ周りが荷物を取っていくのを眺めるだけの時間が過ぎました。

 

荷物が来ないことが確定してからは、上記の通り。

ただ、到着地には2泊しかしないことに少し不安を覚えつつ、深夜のテンションと初めての体験に少々ハイになっていました。

 

もらった日用品

 

申請は上記で書いた通り。

しばらく過ごす用として、日用品をもらいました。女性用と男性用があり、女性用をもらいました。

中身は、下記の通りでした。一晩越すのに助かりました。

  • Tシャツ(Lサイズ)
    パジャマとして使いました。大き目なので、ズボンはついてなかったけど、ワンピース感覚で使いました。
  • 洗濯洗剤
    当日来ていた服をもう一度着るために、洗濯に使いました。
  • 歯ブラシ・歯磨き粉
    海外のホテルにはついてないことも多いので、助かりました。
  • シャンプー
    中国製ですが、ダブです。普通にいい匂い。みんなこれなのか、アジア系だから中国製なのかはわかりませんが、地域によって髪質が全然違うので中国製であることは助かりました。
  • 日焼け止め
    実際には使っていないですが、なぜ真冬に日焼け止め?と少し感じました。オールシーズン同じなんですかね?
  • デオドラント
    海外っぽい!笑 かなりきつめの匂いですが、いわゆる「フローラル」の匂いです。香水文化圏は、匂いをきちんとつけておくのは常識なのかな。
  • ヘアブラシ
    これは日本のホテルにもついているレベルのものでした。ロングヘアーにはすごく助かる。
  • 生理用品
    生理中の方は死活問題ですもんね。幸い使う必要がなかったのですが、ナプキンとタンポンが一つずつ入っていました。ただ、ナプキンは小さめだし、タンポンは上級者仕様(ひもがついてなさそう?)だったので、持参のがあるのがベストですね…。いきなり海外のものを使うのはキツイ…。
  • 爪やすり
    実際には使わなかったけど、いわゆる板状のものです。

 

荷物到着まで

ルフトハンザでは、自分の荷物の現在のステータスを見ることができます。

アマゾンとかで、荷物がどこの集荷所についた、とかそういうのが見れるのと一緒です。

いつ届くのかによって、買わなければいけないものも変わってしまうので、ここはかなり用心して定期的にチェックしていました。

何しろ、移動がそんなに長くなかったので、化粧品等まったくもたずでした…。

 

到着当日は、自分の荷物を洗濯してすぐ寝てしまいましたが、翌朝には荷物がフランクフルトにあって、昼12時着の飛行機で現地に着くことステータスが更新されていました。

その日も仕事でしたが、出発時間のギリギリまでホテル周辺のドラッグストアをめぐって化粧品の調達等をしていました。

夜になり、荷物は届いているはずだけど、届いていなければ追加で購入の必要があるので、ホテルに確認の電話をしたところ、まだホテルには届いていないとのこと。

翌日の朝には出発予定だったので、かなり焦り、空港にもかけてみようと思ったくらいでした。

 

結局フロントにしつこくまだかまだかと聞いていたからか、荷物が届いたのは夜中の0時過ぎだったのですが、内線で届いたと連絡がありました。

翌日用に洋服を既に洗濯していたので、着るものがない状態でしたが、コート一枚で何とか荷物を受け取ることができました。

まとめと反省

結果的には、荷物の紛失を空港で申請してから、ホテルに着くまでは24時間くらいかかりました。

f:id:KashiwaMOCHI:20200430143327p:plain

これは荷物が止まっている空港からの便次第ではあると思いますが、私はハブ空港であるフランクフルトで止まっていたので、比較的早い方ではないかなと思います。

ただ、やっぱり海外でトラブルに合うと本当に焦る!!!海外慣れしている方でも、初めてのトラブルは多少苦労すると思います。

 

実際にロスバゲを経験して、次からは以下実施しようと考えています。

ただ、本当にトランジットの場合くらいかな。ダイレクト便でなくなるのはあまり多くないと思いますので、危ない航路だなと思ったら位の感覚でとらえています。

 

旅行前

  • 荷物リストの作成
    何を入れているかを荷造りの段階で書いておきます。これは、最悪完全ロストや長期間返ってこなかったときに申請時あると便利です。
  • 預入荷物の撮影
    荷物の外観の撮影。もちろん中身も撮影できればあとで確認もできますが…。
    紛失申請時にコミュニケーションが楽になります。
  • 予備品セット
    一番大事!手荷物を軽くしたいけど最低限入れておきたいセットを作って仕込んでおきます。
    これは人それぞれですが、日用品セットにはないものを入れておくのがいいと思います。
    個人的には、化粧水・ファンデーション・口紅・洗顔料・下着セット・生理用品かな
  • 保険の確認
    基本的に、モントリオール条約で補償されるので大丈夫ですが、自分の保険が対象かを知っておいてもいいかなと思います。正直なくていい。

旅行中

  • レシート保管
    買ったもののレシートは保管しておきます。これはロスバゲ後でも前でも一緒。最悪完全紛失した場合は、買ったもの全額補償になりますので。
    クレカ払いだったら履歴残ってるので、基本は他の物に対してかな。
  • チェックイン時の念押し
    トランジットする場合は念押ししておこう。次から絶対。
    途中で荷物を引き取る必要がないか?最終目的地までもっていってくれるか?を確認する。

 

以上、ロスバゲしたときの心得と実体験でした。

役に立たない記事であれば、幸い。

【5日目】KaggleでPythonの勉強してみた【独学】

本日も、KaggleでPythonの勉強をしていきます。 昨日でちょうど折り返ししたのですが、後半がキツイと聞いているので、ここまでも時間がかかってしまっていましたが、もっとかかるかも…。 しっかり進めていきます。

勉強内容

Lesson:Loops and List Comprehensions (Tutorial)

勉強時間:60分

Lesson:Loops and List Comprehensions (Exercise)

勉強時間:60分

TutorialはCourseの和訳(概略)、Tutorialは試行とどう考えていたかを記しています。

Lesson:Loops and List Comprehensions(Tutorial)

Loops

ループは、コードを繰り返し実行する方法です。

ループには、変数とループが可能な値集合をinを使用して実行します。

inのあとの変数は繰り返しをするものであれば何でもいいです。

基本的には、集合体である場合、その分ループを繰り返すことができます。

さらに、リストである場合はその要素数分繰り返すことができるということです。

下記は文章内に含まれている大文字を出すという処理をします。

s = 'steganograpHy is the practicE of conceaLing a file, message, image, or video within another fiLe, message, image, Or video.'
msg = ''
# print all the uppercase letters in s, one at a time
for char in s:
    if char.isupper():
        print(char, end='') 

range()

range()は数字の連続を返す関数です。ループを書く上で非常に使える機能です。 例えば、5回繰り返すときは、 for i in range(5)とかけば、5回繰り返すことになります。

while loops

for文以外のループの方法として、条件を満たすまで繰り返しを続けるwhileがあります。 whileブーリアン文として扱われており、Falseになるまで繰り返します。

List comprehensions

リスト内包はPython独自の特徴です。 いくつかの例を見るのがよいでしょう。

###数の累乗リスト(0~9)
#リスト内包なし
squares = []
for n in range(10):
    squares.append(n**2)

#リスト内包あり
squares = [n**2 for n in range(10)]

また、ifを足すこともできます。

short_planets = [planet for planet in planets if len(planet) < 6]

代入先の変数はループ変数を含む必要はありません。(含まれていないのはかなり珍しいですが。) 究極、代入先がなくてもよいのです。

リスト内包は、minmaxsumと統合でき、これまで長々と書いていた文章を1行にすっきりとまとめることができます。

コードを短くすればするほどいいというわけではないです。 短い方が、よいでしょうが、以下の言葉を覚えておいた方がいいです。

Readability counts. Explicit is better than implicit. (可読性を重視すること。暗黙的なものより明示的な方がよい。)

Lesson:Loops and List Comprehensions (Exercise)

Tutorialはかなりの感動モノでした。

これまであんなに「キチンと」書いていたのに、これほどシンプルでよいのか、という思いと、こういう書き方に慣れていないので、少し時間がかかるかもしれないという印象を受けました。

Q1:次のバグを含んだプログラムに対し、バグを明確にし、直せ

渡されたリストが「ラッキーリスト」であるかを返す関数。「ラッキーリスト」とは7の倍数が少なくとも1つ含まれたリストです。

def has_lucky_number(nums):
    """Return whether the given list of numbers is lucky. A lucky list contains
    at least one number divisible by 7.
    """
    for num in nums:
        if num % 7 == 0:
            return True
        else:
            return False

関数を見ても、これでよくない?と思ってしまいます…。 動作を確認するために、実際にリストを作って入れてみます。

l1 = [1,3,5,8,9,14]
l2 = [2,8,5,3,-7,0]
l3 = [4,6,10]
print(has_lucky_number(l1))
print(has_lucky_number(l2))
print(has_lucky_number(l3))

予想では、l3のみFalseですが、全てFalseになりました。 ループの中身も見てみます。

def has_lucky_number(nums):
    """Return whether the given list of numbers is lucky. A lucky list contains
    at least one number divisible by 7.
    """
    print(nums, len(nums))
    for num in nums:
        print(nums, num, num%7, sep = "\n")
        if num % 7 == 0:
            return True
        else:
            return False

こうすると、ループを一回しか回ってないことがわかりました。 returnがfor文にあるのが原因かも。 7の倍数が一つあればいいので、Trueのみfor文に入れ、Trueになればその時点で関数を抜けますが、最後までならなかった場合、きちんとFalseを返すようにfor文から抜けた個所にreturn Falseを入れました。

愚直にやるとこの方法ですね。 正答例には、一行で書いた場合の例もありました。 anyという方法を知らなかったので、今後活用していくようにします。 もし○○があれば、を書く関数で、そのままTrue/Falseを返してくれるから、らくちんそう。

これ以降は、終わりきらなかったので、次の日へ。

新出単語

iteration:繰り返し comprehensions:包含 subjective:主観の

【4日目】KaggleでPythonの勉強してみた【独学】

KaggleにあるCourseでPythonの勉強ができるのでそのノートです。 前回から、考え方とかしっかり書き残しておきたくて、コードを入れていたのですが、Markdownを知らずやっていてすごく見づらかったので、少しはましになるようにググっておきました。 見やすくなるといいなあ!

Tutorialは、内容の和訳(意訳・概要のみ)でExerciseはそのコードを書いた考え方とか解説を書いておきます。 独学には非常にいいコースなんですが、たまに答えだけではすぐにわからなくなるものが出てきたので、使い分けが必要だなあ。

勉強内容

Lesson:Lists Tutorial

勉強時間:60分

Lesson:Lists Exercise

勉強時間:70分

Lesson:Lists Tutorial 

Listsのコース

List

リストは、変数に行列を入れることができるもの 行列は可読性を考えて(一行でも書けるけど)下記のように書くのがよい。

ABC = [
    ['A', 'B', 'C'],
    ['D', 'E', 'F'],
    ['G', 'H', 'I']
]

リストは同じ種類の型式だけでなく、文字と数字も一気に入れられる。

Indexing

リストに入れた中身を取り出すときは、ABC[0]など数字を入れて呼び出す。 リストは0から始まる。

なお、リストの最後の中身を見るときは[-1]で指定する。(それよりも一つ手前は-2、と数字を減らしていく)

Slicing

リストの中身を連続で複数個取り出すときは、ABC[0:3]のように範囲を指定する。 0が、始まりのインデックス、3が取り出す個数を示す。 一番最初から取り出すときは、ABC[:3]のように省略してもいい。

また、個数を指定せず、「〇個目から全部」のように指定したいときは、始まりの数をxとおいて、ABC[x:]と書ける。

最初と最後を省くとき:ABC[1:-1]

最後の3つのみ取り出す:ABC[-3:]

Changing lists

リストの中身を変更するときは、変更する場所を指定して、代入すればよい。

ABC[:3]=[1,2,3]とすればABCが123へ置き換わる。(一気に代入)

List functions

リストの長さ:len()

ソート(ABC順、昇順?):sorted()

合計:sum()

最大値:max()

Interlude: objects

ここまで度々'object'という言葉が出てきたが、解説する。 Pythonではドット構文によってアクセスできる。 例えば虚数を出したいときは、int代入した変数に変数.imagで出すことができる。

この類のオブジェクトは関数を含むこともできる。関数を含んだオブジェクトのことをメソッドと呼ぶ。 関数を含んでいない(.imagとか)はアトリビュートと呼ばれる。

例えば、関数を持つbit_length変数.bit_length()と書く。

ヘルプで呼ぶときは、普通にhelp(bit_length)でもいいし、help(変数.bit_length)でも呼ぶことができる。

List methods

リストに関するメソッドを解説する。

リストの最後に新しい内容を付け加える:list.append

※helpするときは、help(append)だとあまり有益な内容が書いてないので、help(list.append)がよい

最後の内容を削除する:list.pop()

Searching lists

list.index:検索したい単語を()に入れるとどのインデックスにあるかを返す。 検索したい単語がリストにあるかどうか "A" in ABCを出すと存在するとTrue、存在しないとFalseが返ってくる。

リストそのものをhelpすると他にもたくさんの機能が出てくるので、参照するといい。

Tuples

タプルはほぼリストと同じ。

  1. リストの中身は[]で宣言するのに対して、()を使う
x = (1, 2, 3)
x = 1, 2, 3

どちらでも中身を入れることがでっきる。 2. 変更が不可能。

タプルの使用例 複数の返り値を持つ関数で使われる。

例えば、実数を分数で表現するas_integer_ratio() 普通に使うと

x = 0.125
x.as_integer_ratio()

(1,8)

タプルは括弧がいらないので、こんなことも可能

numerator, denominator = x.as_integer_ratio()
print(numerator / denominator)
新出単語

Interlude:幕間、中間 utterly:まったく、すっかり obscure:ぼんやりした tuple:有限な列の長さ immutable:不変の

Lesson:Lists Exercise 

Q1:関数を完成せよ。(リスト2番目)

リストの2番目のエレメントを返す。ただしエレメントがない場合はNoneを返す。 これは割と簡単にlen()を使えばいい

Q2:関数を完成せよ。(最下位チームのキャプテン)

あなたはスポーツチームを分析しています。各チームのメンバーは順にリストに入っています。リストの先頭はコーチで、その次がキャプテン、メンバーと続きます。このリストは成績順に並んでいます。最下位のチームのキャプテンを返す関数を作成してください。

こんな感じかな…。英語からこれが正しいと理解するのに、時間がかかってしまった。

順位 コーチ キャプテン メンバー1
優勝 〇〇 〇〇 〇〇 〇〇
最下位 ×× ×× ×× ××

Q3:関数を完成せよ。(マリオカート

次回のマリオカートのアップデートでは、「パープルシェル」というアイテムが登場する。使用すると最後尾の選手を1位に、1位の選手を最後尾にワープさせる効果を持つ。その効果を発動させる関数を完成させよ スワップの方法は、初期のExerciseで実施済み。それと同じ形で行えばよい。

Q4:len()を使わずに、各リストの長さを予想せよ。

len()を使えばすぐわかる答えですが、どういうものかを把握しておけ、ということですね。 len()は行列になっているとき、行数を数えることがわかりました。列数だと思っちゃいそう。ちょっと危ないです。

Q5:関数を完成せよ。(”ファッショナブル”にパーティに遅刻する方法)

party_attendeesにはパーティに来た人とその順番が書かれています。パーティーのゲストは少なくとも到着順の半分より後に到着した場合、「ファッショナブルに遅れた」とみなされます。しかし、最後であってはなりません。パーティーの参加者リストより、指定した人がファッショナブルに遅刻してきたかを返す関数を作成しなさい。

実際に書き出してみました

1人目(0) 2人目(1) 3人目(2) 4人目(3) 5人目(4) 6人目(5) 7人目(6)
Adela Fleda Owen May Mona Gilber Ford
Adela Fleda Owen May Mona Gilber なし

人を探すときはindexを使うけど、長さは+1になることを注意しないとですね。 表では偶数と奇数を並べて、どういう計算が正しく半分を指定できるか見比べました。 これをもとに愚直にコードを書いて

def fashionably_late(arrivals, name):
    """Given an ordered list of arrivals to the party and a name, return whether the guest with that
    name was fashionably late.
    """
    order = arrivals.index(name)
    
    if ((len(arrivals)-1)//2)<order <(len(arrivals)-1):
        return True
    else:
        return False

これでも正解はするけど、正答例はもっとかっちょいいです。

def fashionably_late(arrivals, name):
    order = arrivals.index(name)
    return order >= len(arrivals) / 2 and order != len(arrivals) - 1

私がif文で書いたものと一緒だけど、確かにReturnのところでTrue/Falseを判断させればいいもんなー こういう書き方あまりしないので、意識して書いた方がいいなあと思いました。

新出単語

iteration:繰り返し infuriate:激怒する

【3日目】KaggleでPythonの勉強してみた【独学】

KaggleのCourseタブからPythonの勉強ができるのでそのノートを取ります

 

Lesson:Booleans<Exercise>

勉強時間:120分以上

 

Lesson:Booleans<Exercise>

 Q1:入力値が正であれば1、負であれば-1、0であれば0を変えすsign関数を作成せよ。

 

Q2:入力値が1の場合はprintの内容を単数形、複数の場合はprintの内容を複数形で返す関数を作成せよ。

 

Q3:定義されている関数のバグを探せ。

 当たりはつけてたけど、特定に時間をかけてしまった。

Q4:負の数だけTrueを返す関数を作成せよ

 

Q5:ホットドッグの3つのトッピングが下記の場合にTrueを返す関数を作成せよ。

①オニオン抜き

②すべてのトッピングなし

③ケチャップ・マスタードどちらかを選んだ場合

問題を勘違いして、めちゃくちゃ難しく考えてしまった…。

無駄な時間…。

ベン図を使うとすぐわかる。

Q6:④一つのトッピングのみをオーダーした場合。

bool()に対してint()を呼ぶとどうなるだろうか?またそれを利用して簡潔な関数を書くこと。

bool(int())はTutorialで行っている通り、0以外はFalseで返す。

int(bool())にするとどうなるか?

これは、関数外で、やってみるとすぐわかるけど、True=1, False=0になる。

ベン図じゃなくて、一覧表を書くと容易に四則演算で何とかなることわかる。

 

www.cs.shinshu-u.ac.jp

 

Q7:(選択問題)ブラックジャックでプレイヤーになってコントロールする関数を作る。

  • プレイヤーは2枚のカードをもち、ディーラーは1枚のカードを持つ。
  • プレイヤーは何回でも”ヒット”によってカードを受け取ることができるが、カードの合計が21を超えるとラウンドは終了し、負ける
  • ディーラーは以下を満たすまでカードを配り続ける。
  1. ディーラーのカード合計が21を越したとき。(プレイヤーの勝ち)
  2. ディーラーのカード合計が17を超え、かつ、プレイヤーのカード合計がディーラーのカードより大きい場合。(プレイヤーの勝ち)
  3. それ以外の場合はディーラーの勝利

合計の計算

ジャック・クイーン・キングは10

エースは合計が21を超えないように、1または11として数える。

 

ゲームで勝率を上げられるか。これは正解も何もないんだけど、条件式の練習です。

ちなみに結果(デフォルト)は勝率38.3%(5万回試行、以下すべて)で、ブラックジャックはディーラーの勝率の方が高いといわれているそうなので、50%を超えれれば万々歳です。

 

一応ルール的に17以上はヒットしない方がよいようにみえたので、17あればヒットしない関数を作りました。
if player_total<=17:
return True
else:
return False

結果(条件1つ追加)は勝率39.4%

あんまり変わらないですね。

条件式の練習なので、戦略は下記のベーシックストラテジーを参照にしてみます。

chisou-sympo.jp

 

ここではスタンドとヒットしかできないので、Rはヒット、Dはヒット、Dはスタンドとします。

スプリットは今回のルールではできない…。ので、スプリットは一回無視します。

=ハードハンドとソフトハンドのみ

ちょっと面倒くさくなってるところは、ちょっと省く感じで笑

返り値 プレイヤー手札 ディーラー手札 Aあり/なし
ヒット(True) 8~11 問わない なし
  13~16 7~A なし
  12 2~3 なし
  12 7~A なし
スタンド(False) 13~16 2~6 なし
  17 問わない なし
  12 4~6 なし
ヒット(True) 2~6 問わない あり
スタンド(False) 7~8 問わない あり

 

関数のきれいさは置いておいて、愚直にコーディングしていきます。

if player_high_aces == 0:
if 8<=player_total<=11:
return True
elif (13<=player_total<=16) and (7<=dealer_total<=10):
return True
elif player_total == 12 and *1:
return True
elif (13<=player_total<=16) and (2<=dealer_total<=6):
return False
elif player_total == 12 and (4<=dealer_total<=6):
return False
elif player_total == 17:
return False
elif player_high_aces ==1:
if 13<=player_total<=17:
return True
if 18<=player_total<=19:
return False

 

そして結果は…

結果(ベーシックストラテジー)は 勝率42.3%

 

確かに、勝率上がったものの、+3%かーーーー!

こういうたぐいの勝率を上げるのは、大変なんですよね。

ちなみに一般的な勝率は47~48%らしいので、全然届いていません。

 

勝率を出すのは5万回試行ですが、1回のみ試すという関数もあって実行してみました。

------------------------------------------------

Player starts with 2 and A (total = 13)
Dealer starts with K

__Player's turn__
Player hits and receives 3. (total = 16)
Player hits and receives 8. (total = 14)
Player hits and receives 10. (total = 24)
Player busts! Dealer wins.

------------------------------------------------

Player turnの2列目(赤字)ところ、なんでこうなるんだろう。

ここで14になる理由がわかってないので、多分相変わらずここの英語が読めてないのかなー笑

------------------------------------------------

Player starts with 3 and 3 (total = 6)
Dealer starts with 8

__Player's turn__
Player stays

__Dealer's turn__
Dealer hits and receives 3. (total = 11)
Dealer hits and receives 5. (total = 16)
Dealer hits and receives 6. (total = 22)
Dealer busts! Player wins.

------------------------------------------------

ステイをとるとこういう挙動

DealerのTurnになるとPlayerは動かないのか。

したら、確かにデフォルトの「Stayしかとらない」という戦略はDealerの自爆を誘発するだけだから、ある程度ありうる戦略なのかも

 

 

もう少し勝率をあげに行きたいところだけど、この関数は仕組みがブラックボックスになっているし、試行の中身がわからない=何が敗因だったかわからないので、以上でやめることにしました。

 

この設問に関しては解がないので、残念ながら参照することもできず。

奥が深いよなー

 

ブラックジャックの他の人の回答はこんな感じ。

42%を引っ提げていくとあまり悪くはない気がする。

www.kaggle.com

 

一つだけ面白そうなのを見つけたので、真似してみました。

結果は見事!

Player won 50000 out of 50000 games (win rate = 100.0%)

関数の裏を突いたのかなあ。追加行はたった3行だけでした。すごい笑

 

<新出単語>

get credit:面目を施す

verbose:くどい、冗長な

 

 

*1:2<=dealer_total<=3)or (7<=dealer_total<=10

【2日目】KaggleでPythonの勉強してみた【独学】

KaggleのCourseタブからPythonの勉強ができるのでそのノートを取ります

 

【2日目】

Lesson:Hello, Python <Exercise>

勉強時間:30分

Lesson:Functions and getting help <Tutorial>

勉強時間:30分 

 

Lesson:Functions and getting help<Exercise>

勉強時間:30分 

 

Lesson:Booleans<Tutorial>

勉強時間:30分  

 

 Lesson:Hello, Python <Exercise>

<内容のメモ>

Notebookの使い方

 コードの実行:ctrl+Enter

上にセルを追加:セルを選択→Esc→a

下にセルを追加:セルを選択→Esc→b

 

Question0では回答の見方・ヒントの見方が出てくる

color = "Blue"って打つ

チェック「違うよ。回答の見方とかヒントの練習をするために、ヒントを見てね」

ヒント「glueと韻を踏んでるよ」

(韻を踏んでる=Rythmがわからず)color = "glue"と打つ

チェック「え、めっちゃうけるw」

いい意味でイラっとした

 

コードを解くのが楽しかった!

 

<新出単語>

diameter:直径

vice versa:逆に

 

Lesson:Functions and getting help <Tutorial>

<内容のメモ>

ヘルプ:help() →①引数②関数の定義・働き を解説してくれる

今の段階では必要がないけど、後々複雑になるにつれて、関数の中身を理解する上ですごく役に立つ。
ここでの②のことをdoctringという。

関数の定義
return:関数を出るときの宣言。また何を関数の解にするのかを書く。
自分の関数を作ると、docstringを入れておかないと、help()に入れても何も解説してくれない。
dosctringの作り方:"""でくくる(ダブルクオーテーション3つ)
あまり使わない関数ほど、docstringを作っておくと役に立つよ。

printの面白い機能

printにはsepという機能があり、カンマで区切られた単語の間に挿入する単語をかけたりする。(下記で<を書かなければシンプルに1 2 3だけ印字される)

print(1, 2, 3, sep=' < ') 
1 < 2 < 3

 

関数を作るとき: def 関数名(引数)

関数内関数(関数の中で関数を呼ぶ)は下記でできる。

→ def 関数名(fn, arg) : return fn(arg) 

→print関数だと、最後にkey = 関数名を使うと、関数を使った結果が印字される

 

<新出単語>

docstring:Python用語。関数とかクラスに関してユーザーが残しておくコメント

qiita.com

voluminous:(形)おびただしい
configurable:構成可能
inscrutable:(形)不可解な

aka:as know as 別名

 

Lesson:Functions and getting help<Exercise>

 

 Q1:docstringの内容に沿って関数を完成せよ。

  関数→小数点2桁までに数を丸めること(3.1415なら3.14)

※passはPythonの性質上、関数の中に何か書かなければいけないので、意味はないが書いてるだけの行

<感想>

純粋にPythonの一般的な関数を知らないから、四則演算でなんとかするのかな…と思いきや、hintを見て、割とシンプルなつくりだなあと(そりゃ関数になれるためのパートだもんね)

 

Q2:round関数にはndigitsが負の数をとることがあること書かれている。試してみること

<感想>

Excel関数でよく使っていたので、すんなりできた

 

Q3:ハロウィンで集めた総キャンディ数を友人間で等分し、余りはつぶすこととする。キャンディ数と友人数を引数とする関数を作成すること。なお友人数が定義されない場合は3人とする。

<感想>

無駄なことを考えてしまった。

if文使って場合分け、と考えたけど、まだif文はTutorialには出てきてないので混乱した。しっかりTutorialを見れば確かにわかる。

 

Q4:エラー構文を読む練習。エラーを吐く構文を実行し、正しく直せ。

コメントを外す:Ctrl+/

 

<新出単語>

decimal :(名)十進法の、少数の

 

<感想>

Exerciseはやってて面白いものだけど、今回は割とすんなりできた。

 

Lesson:Booleans<Tutorial>

正誤判定:bool

TrueやFalseを変数に直接入れるよりも、比較演算子で正誤判定をすることの方が多い。

Operation Description   Operation Description
a == b a equal to b   a != b a not equal to b
a < b a less than b   a > b a greater than b
a <= b a less than or equal to b   a >= b a greater than or equal to b

比較演算子では、intとfloatを比較することはできるが、stringとintは無理

returnのところで、and, or, notをつけたりすることで、さらに条件を付けた関数にもできる。

and, or, notには優先があって、andの方が高いと決まっている。

True or True and False

例で出てきた、上記は True or (True and False)と読め、True and Falseは存在しないが、Trueであればいいので、解はTrue

もし、orの方が上位の場合は結果も変わり、(True or True) and Flaseで、True or True =TrueとFalseが同時に成り立つものは存在しないので、解はFalseとなる。

この書き方は結構なバグの可能性を秘めているので、()で囲ってしまう方が可読性も高く、よいコードである。

条件文:if, elif, else

bool関数における正誤

数字:0以外のすべての数字はTrue

文字:何か文字が入っていればTrue

上記をうまく使えば、ifは比較演算子がなくても成立する。if 0:だと、Falseの場合、みたいな使い方ができる。

 

<新出単語>

 precedence :優先権、上位

denote:(動)示す

implicitly:暗に

 

<感想>

内容難しかった。Bool自体他の言語と変わらないんだけど、サンプルを理解するのに少し時間がかかってしまった。