在宅リーマン勉強日誌

忘れがちな毎日のメモ。

【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:専門語