pythonのprastクラスによる集計(2) クロス集計

2018/09/22

 pythonで定番の単純な集計を行う目的で prast.py を自作しました。

 今回はクロス集計を取り上げます。

 処理するcsvファイルは前回と同じ data01.csv です。

 当Webページで紹介するスクリプトや素材データ一式は、
prast02.zip という圧縮ファイルに同梱しておきます。

    


《このページの目次》


    

1. クロス集計表を作るための tableメソッド

 Prastクラスに table() というメソッドを設けてあります。
クロス集計を行うものです。

 たとえば下のような表を作成します。

  賛成 反対 保留
男性 73 98 30
女性 78 96 18

 これはgender(性別)とopinion(意見)の組み合わせで人数を数え上げたものです。

dod = psx.table("gender", "opinion")

 上のように書くと「性別」×「意見」のクロス集計表が得られます。

 2つの引数は必須で、それぞれの列ラベルを指定します。

 戻り値dod(OrderedDict型)には上記の表の他に
合計欄を付加した度数の表と、2種類のパーセンテージの表が入ります。
つまり4つの表が得られます。

 パーセンテージの表は、横方向に足し算をしたときの合計を100%とする表と、
縦方向に足し算をしたときの合計を100%とする表の2種類です。

  賛成 反対 保留 合計
男性 36.3 48.8 14.9 100.0
女性 40.6 50.0 9.4 100.0
合計 38.4 49.4 12.2 100.0
  賛成 反対 保留 合計
男性 48.3 50.5 62.5 51.1
女性 51.7 49.5 37.5 48.9
合計 100.0 100.0 100.0 100.0

目次に戻る


2. クロス集計用のスクリプト

 4つのクロス集計表を表示するスクリプトは次のとおり。

 1# table01.py (coding: cp932)
 2import pandas as pd
 3from prast import Prast
 4
 5dtf = pd.read_csv("data01.csv")
 6psx = Prast(dtf, "data01_c.txt", "data01_i.txt", "cp932")
 7dod = psx.table("gender", "opinion")
 8for key in dod.keys():
 9    print(key)
10    print(dod[key])
11    print('')

 変数dod(OrderedDict型)のキーは name, tbl1, tbl2, pct1, pct2 です。

 nameは、どの列とどの列のクロス集計かを示すもので
「性別/意見」などの文字列です。

 それ以外の tbl1 などは、いずれも DataFrame です。

 pct1, pct2 の小数点以下の桁数を2桁にしたいときは
事前に psx.cround = 2 という1行を置きます。

psx.cround = 2
dod = psx.table("gender", "opinion")

目次に戻る


3. 欠損値も数えあげてcsvとして出力

 先のスクリプトでは欠損値が対象外になっています。

 欠損値も数え上げるのであれば下のように事前に fillna() を呼び出します。

psx.fillna()
dod = psx.table("gender", "opinion")

 欠損値も数え上げ、出力をcsvファイルにするスクリプトを掲げておきます。

 1# table02.py (coding: cp932)
 2import os
 3import pandas as pd
 4from prast import Prast
 5
 6dtf = pd.read_csv("data01.csv")
 7psx = Prast(dtf, "data01_c.txt", "data01_i.txt", "cp932")
 8psx.fillna()  # object型の列の欠損値に名前付け
 9dod = psx.table("gender", "opinion")
10name = dod.pop('name')
11out_file = "table02.csv"
12if os.path.exists(out_file):  # out_fileが存在するなら削除
13    os.remove(out_file)
14with open(out_file, "a") as f:
15    f.write(name + "\n")
16    for key in dod.keys():
17        dod[key].to_csv(f, encoding="cp932")
18        f.write("\n")  # 区切りとして空白行を書き込む

目次に戻る


4. 度数の表とパーセンテージの表を一つにまとめる

 度数とパーセンテージを一つにまとめて
 各セルを「度数(パーセンテージ)」の形式にしたいことがあります。

 73(36.3) のようにパーセンテージを括弧に入れて付加する形です。

 table() で度数の表とパーセンテージの表が得られるので
2つの表の対応する各セルを結合すればいいことになります。

  賛成 反対 保留 合計
男性 73(36.3) 98(48.8) 30(14.9) 201(100.0)
女性 78(40.6) 96(50.0) 18(9.4) 192(100.0)
合計 151(38.4) 194(49.4) 48(12.2) 393(100.0)

 この結合のためのメソッド join_table() を設けてあります。

 ただ、これは Prastクラスのメンバーメソッドではありません。

 prast.py の中で一般的なメソッドとして定義してあります。

    

dtf = join_table(dtf1, dtf2, fmt="%s(%s)")

 戻り値は結合した結果(DataFrame)です。

 第1引数と第2引数は、結合の材料となる DataFrame 。

 第3引数の fmt は、セルの書式を指定するものです。

 %記法の書式(他言語のsprintfと同じ)で指定します。

 省略すると "%s(%s)" になります。

 サンプルのスクリプトは下のとおり。

 1# table03.py (coding: cp932)
 2import pandas as pd
 3import prast as ps
 4
 5dtf = pd.read_csv("data01.csv")
 6psx = ps.Prast(dtf, "data01_c.txt", "data01_i.txt", "cp932")
 7dod = psx.table("gender", "opinion")
 8dtfx = ps.join_table(dod['tbl2'], dod['pct1'], "%d(%5.1f)")
 9print(dtfx)

 書式を "%d(%5.1f)" としているので
小数点の位置がそろうのではないかとおもいます。

 Prastクラスに属していない join_table() を呼び出す関係で
今回は import prast as ps としました。

 そうしておけば ps.join_table() として呼び出すことができます。

〜 以上 〜

Copyright (C) T. Yoshiizumi, 2018 All rights reserved.