データサイエンス

PDFからテーブルデータを取得

2023年5月22日

前回、国土交通省のウェブサイトから高速道路の日次交通量のPDFファイルをダウンロードしました。
今回はダウンロードしたPDFを読み込み、PDFファイルの中にある表(テーブルデータ)を取得してCSVに保存します。
PDFファイルから表を取得するにはPythonのtabulaパッケージを使用しています。

CSVに保存したデータの可視化・考察まで含めた分析全体については次のページにまとめています。

参考コロナ前後の高速道路の交通量の推移

今回は、高速道路の交通量データの可視化を行い、コロナ禍の外出自粛による交通量激減からの回復状況の区間ごとの違いを見ていきます。 今回使用するデータは、ダウンロードや構造化データに直すまでに一手間かかる ...

続きを見る

PDFからテーブルを取得~CSVに保存

前回は、国土交通省の下記ページから、高速道路の日次交通量データを取得しました。

全国・主要都市圏における高速道路・主要国道の主な区間の交通量増減(国土交通省)
※このデータを使用した分析全体はこちらを参照

今回は取得したPDFから交通量のテーブルを取得してCSVに保存します。
使用するパッケージは次のとおりです。

import tabula
import re
import glob

PDFの読み込みと表の取得には、tabulaパッケージのread_pdf関数を使用しました。
PDFには取得したいテーブルデータ以外の情報もあるので、read_pdf関数の引数を調整して必要な部分だけを取得する必要があります。

日ごとのPDFファイルの構造は、1ページ目に対象区間を示した地図、2ページ目に交通量の表が掲載されています。
2ページ目の表は2つに分かれており、1つ目のデータを取得します。
この表はエクセルのセル結合を使っているため、そのまま読み込もうとすると読み枠が崩れるやっかいなファイルです。
そのため、read_pdf関数のarea引数の数値を調整し、セル結合している部分をあえて読み取り対象範囲から外すことで読み枠が崩れるのを回避して読み込みました(次のコードを参照)。

# 関数定義:PDFからCSVを取得
def get_table(pdf):
    # PDFからdfを取得
    dfs = tabula.read_pdf(
        pdf,       # PDFファイル
        pages=2,    # 抽出ページ
        guess=False,     # 分析部分の変更有無
        #area='entire',  # ページの部分指定
        area=[0, 128, 800, 1600], # セル結合している左端のセルを回避して読み込む
        lattice=True,  # 格子区切りがPDF内にある場合の対応
        stream=False,   # ストリームモード
        password=None,  # パスワード
        )
    # 複数のテーブルのリストとして得られる
    # 必要なのは最初のdf
    df = dfs[0]

    # テーブルデータの整形・出力
    df = processing_df(df=df) # 自作関数

    # ファイルパスから日付を取得
    regex = '.*高速道路交通量_全国_日別_(20[0-9]{2}-[0-9]{2}-[0-9]{2}).pdf'
    date = re.match(regex, pdf)[1]
    
    # CSV出力・保存
    out_path = '../02_work/02_高速道路日別交通量_csv/02_高速道路交通量_全国_日別_' + date + '.csv'
    df.to_csv(out_path, index=False, encoding='cp932')

読み取ったテーブルデータを見やすいように整形します。
和暦を西暦に直したり、細かいスペースや余計な文字等を修正します。

# 関数定義:テーブルデータの整形
def processing_df(df):
    # NAのレコードを削除
    df = df[~df['都道府県名'].isna()]
    df = df[df['都道府県名']!='合 計']
    df = df[df['都道府県名']!='平均']
    
    # カラム名に入った改行記号などを削除
    # 削除したい箇所を正規表現でリスト化
    regex_list = ['\r', '[0-9]\(台/日\)']

    for regex in regex_list:
        df.columns = [re.sub(regex, '', col) for col in df.columns]
    
    # df.columns = [col.replace('\r', '') for col in df.columns]
    # 和暦を西暦に変換
    df.columns = [col.replace('令和4年', '2022年') for col in df.columns]
    df.columns = [col.replace('令和3年', '2021年') for col in df.columns]
    df.columns = [col.replace('令和2年', '2020年') for col in df.columns]
    df.columns = [col.replace('令和1年', '2019年') for col in df.columns]
    df.columns = [col.replace('平成31年', '2019年') for col in df.columns]

    # 箇所名の表記を置換
    df['箇所名'] = df['箇所名'].str.replace(' ※[0-9]', '', regex=True)
    df['箇所名'] = df['箇所名'].str.replace('~', '~', regex=True)
    df['箇所名'] = df['箇所名'].str.replace(' ', '', regex=True)

    return(df)

以上のように取得したPDFの2ページ目からテーブルデータを取得し、使いやすい形でCSVファイルに保存することができました。

参考文献

全国・主要都市圏における高速道路・主要国道の主な区間の交通量増減 国土交通省 2023/5/18閲覧

-データサイエンス
-, , ,