Python 100本ノック その2

  • Pandas
  • 前回(Python 100本ノック その1)の続きです。

    今は『Python実践データ分析100本ノック』という本を進めています。

    この本は、1~100本目まで例題をひたすらこなしていくという内容になっています。

    実際に手を動かしていて難しかったところを書き残していきます。

    DataFrameにindex(インデックス)があることを知る

    ノック25本目の解説で分からなかったポイントが、こちらの groupby の中で使用されている『as_index=False』です。

    use_log.groupby(["YYYYMM","customer_id"],as_index=False).count()

    そもそもDataFrameのas_indexは何ぞや?という感じです。

    データベースのindex(インデックス)は多少は理解していましたが、DataFrameのindex(インデックス)は今まで考えたことがありませんでした。

    そんなPythonを初めて2週間目の私が解説したいと思います。

    DataFrameのindex(インデックス)とは

    まずは、以下のサンプルデータを見てください。pinkで色付けしている部分がindex(インデックス)です。

    >>> df = pd.DataFrame({ ... 'YYYYMM':["201804","201804","201804","201805","201805","201805","201805","201805","201805","201806"], ... 'userid':["A01","A01","B02","A01","A01","B02","B02","B02","B02","B02"], ... 'flag':["1","1","1","1","1","1","1","1","1","1"]}) >>> print(df) YYYYMM userid flag 0 201804 A01 1 1 201804 A01 1 2 201804 B02 1 3 201805 A01 1 4 201805 A01 1 5 201805 B02 1 6 201805 B02 1 7 201805 B02 1 8 201805 B02 1 9 201806 B02 1

    一番左の数字0~9とあります。これがindexだったんですね~。こんな感じでindexを表示することも出来ます。

    >>> print(df.index.values) [0 1 2 3 4 5 6 7 8 9]

    また、特定の列をindexにすることも出来ます。こうすることで、思いのままにデータの検索が出来るようになります。

    >>> df_i = df.set_index('YYYYMM') >>> print(df_i) userid flag YYYYMM 201804 A01 1 201804 A01 1 201804 B02 1 201805 A01 1 201805 A01 1 201805 B02 1 201805 B02 1 201805 B02 1 201805 B02 1 201806 B02 1 >>> >>> df.set_index('userid').loc["A01"] YYYYMM flag userid A01 201804 1 A01 201804 1 A01 201805 1 A01 201805 1

    groupby の 『as_index=False』

    そして、ようやく本題のgroupbyの登場です。『as_index=True』『as_index=False』とは何なのか。それぞれの実行結果を見てみましょう。

    >>> df.groupby("YYYYMM").count() userid flag YYYYMM 201804 3 3 201805 6 6 201806 1 1 >>> >>> df.groupby("YYYYMM",as_index=True).count() userid flag YYYYMM 201804 3 3 201805 6 6 201806 1 1 >>> >>> df.groupby("YYYYMM",as_index=False).count() YYYYMM userid flag 0 201804 3 3 1 201805 6 6 2 201806 1 1

    groupbyに『as_index=True』を追加するのと、何もしないのでは同じ結果になりましたね。"YYYYMM" が自動的にindex(インデックス)にされています。

    逆に、『as_index=False』を指定した場合は "YYYYMM" はindex(インデックス)になっていません。

    複数の列をgroupbyに指定した場合

    続いては、複数の列をgroupbyに指定した場合はどうなるでしょうか。『as_index=True』と『as_index=False』を指定した場合、それぞれの結果を表示してみます。

    >>> df.groupby(["YYYYMM","userid"],as_index=True).count() flag YYYYMM userid 201804 A01 2 B02 1 201805 A01 2 B02 4 201806 B02 1 >>> >>> df.groupby(["YYYYMM","userid"],as_index=False).count() YYYYMM userid flag 0 201804 A01 2 1 201804 B02 1 2 201805 A01 2 3 201805 B02 4 4 201806 B02 1

    『as_index=True』を指定したときは、いわゆる複合index(インデックス)の状態になっていますね。"YYYYMM" と "userid" で一意になる値のセットがindex(インデックス)となっています。

    ここまで来ると結果が予想できます。『as_index=False』を指定したときは、行番号がindex(インデックス)となっています。

    そもそも ノック26本目の課題とは

    読み込んだデータを、"YYYYMM" と "userid" で集約した DataFrame を作ることでした。それは以下で実現可能です。

    >>> df["flag"] = df["flag"].astype("int") >>> df_flag_sum = df.groupby(["YYYYMM","userid"],as_index=False).sum() >>> df_flag_sum.rename(columns={"flag":"flag_sum"},inplace=True) >>> df_flag_sum YYYYMM userid flag_sum 0 201804 A01 2 1 201804 B02 1 2 201805 A01 2 3 201805 B02 4 4 201806 B02 1

    ※"flag" はint型に変換して sum 出来るようにしています。

    ※rename の引数 inplace を True にすると、元の DataFrame が変更されます。

    先が長い

    100本ノックといえども、まだ26本目です。まだ半分にも到達していない。。。

    明日も頑張ろう。。。

  • Pandas