Python 数万行のデータからグループ分けして抽出する

'21/08/07更新
 pandasのgroupbyメソッドを用いることで、比較的容易に出来ます。

    # 指定した列名にある要素でグループを作成する
    df_group = df.groupby('列名')

# グループ数を数える場合
print(len(df_groupby.count()))

 本記事では、その例題として、日本国内の住所が記載されているデータベース(以下、DB)から、都道府県別に住所データを抽出する雛形コードを載せました。データの入手は、次のリンク先の日本郵政のページからできます。https://www.post.japanpost.jp/zipcode/dl/roman-zip.html

ダウンロードしたzipファイルを解凍(展開)すると下図のようなcsvファイルがあります。12万行(件)あります。

f:id:HK29:20200823233629p:plain

このデータから、pandasのgroupbyを用いることで、下図のように都道府県別にフォルダを自動作成できます。

f:id:HK29:20200823233903p:plain

そして、下図は大阪府の場合のフォルダ内です。10_大阪府.txtと大阪府内の市区別csvファイルが保存しています。これもgroupbyメソッドを用いてグループ分けすることで出来ます。

f:id:HK29:20200823234146p:plain

「10_大阪府.txt」を開くと、下図のように大阪府池田市には43の町があることがわかります。groupby.count()で、数をカウント出来ます。

f:id:HK29:20200823234358p:plain

そして、「池田市.csv」を開くと、池田市内だけの町名一覧がわかります。

f:id:HK29:20200823234556p:plain

■本プログラム

import os
import pandas as pd
import glob

def pandas_groupby_func(DF, folder, target1, target2):
    # 指定した列名にある要素でグループを作成する
    df_groupby = DF.groupby(target1)
    print(df_groupby.count())
    # グループ数を数える
    print(len(df_groupby.count()))
    print(r"#########")

    for name, group_df in df_groupby:
        df1 = group_df.groupby(target2)
        print(name, len(df1.count()))
        path_list = [folder, folder + '.txt'] # ファイルパスをリストで設定
        with open(os.path.join(*path_list), 'a') as f: # ファイルパスをアンパック代入で指定
            f.writelines([name, ',', str(len(df1.count())), '\n'])
        # グループ分けしたデータをcsvファイルで保存
        path_list = [folder, name + '.csv']
        group_df.to_csv(os.path.join(*path_list), 
                        index=False,
                        encoding='shift_jis')


def main():
    df = pd.read_csv(input_file,
                     header=None,
                     encoding='shift_jis') # 'utf-8'
    df.columns = column_names # 列名を挿入する
    
    # 拡張子なしファイル名の取得
    myfolder_name = os.path.basename(input_file).split('.', 1)[0]
    # フォルダを作成
    os.makedirs(myfolder_name, exist_ok=True)
    pandas_groupby_func(df, myfolder_name,
                        target_column_name1, target_column_name2)

    # フォルダ内にあるcsvファイルをリストで取得
    input_file_list = glob.glob(myfolder_name + '/*.csv')
    # 取得したcsvファイルリストを順に処理する
    for i, myfile in enumerate(input_file_list, start=1):
        myfolder_name = str(i) + '_' + os.path.basename(myfile).split('.', 1)[0]
        os.makedirs(myfolder_name, exist_ok=True)
        df = pd.read_csv(myfile,
                         encoding='shift_jis')
        pandas_groupby_func(df, myfolder_name,
                            target_column_name2, target_column_name3)


if __name__ == '__main__':
    input_file = 'KEN_ALL_ROME.CSV'
    
    # 列名がないため、列名をリストで設定する。
    column_names = ['郵便番号','都道府県','市区','町','todoufuken','shiku','machi']
    # グループ分けしたいカウントしたい列名を指定
    target_column_name1 = '都道府県'
    target_column_name2 = '市区'
    target_column_name3 = '町'

    main()

以上

<広告>