Cover Image for OpenRefineの使い方をまとめていく【データ分割:OpenRefine API使用】
OpenRefineの使い方をまとめていく【データ分割:OpenRefine API使用】

image

ども、k69 です。

OpenRefineというデータ整形(データ前処理)ツールで「データ分割」をやってみました。
OpenRefineのGUIではテーブル分割(1つのプロジェクトを複数に分割)する機能を見つけることができなかったので、pythonでOpenRefine APIを呼び出してデータ分割をやってみました。

他にもいろいろなパターンを試しているので
 「【まとめ】OpenRefineの使い方をまとめていく」も参考にしてください。

「データ分割」について説明

ここではプロジェクト(データテーブル)を10カラム(列)ごとに分割し、新規プロジェクトを作成しOpenRefineに登録します。

image.png

データ整形前

29カラム(列)の1つのプロジェクトの状態です。

データ整形後

10,10,9カラム(列)の3プロジェクトに分割されます。

OpenRefineでデータ整形する手順

では、さっそくOpenRefine APIで操作してみましょう。

データの取り込み

データダウンロード

CSVデータはこちら(右クリック→名前を付けてリンク先を保存)からダウンロードできます。

OpenRefineにCSVデータ取り込み

1. ダウンロードしたファイルを選択し、Next を押下します

image.png

2. 文字化けした場合はUTF-8を設定します

image.png

3. プロジェクトを作成します

image.png

プロジェクトを作成したときにプロジェクト番号が作成されるので、ブラウザのURLに表示される番号をメモしておきます。
image.png

4. Jpyter Notebook などで下記のpythonコードを実行します。

★ の部分は環境に合わせてください

OpenRefineデータ分割
import csv
import requests
import json
import pandas as pd

# reference: https://github.com/OpenRefine/OpenRefine/wiki/OpenRefine-API

# Please change OpenRefine params
url='http://127.0.0.1:3333'     # ★OpenRefine URL
project_id = 1681568915441      # ★Project ID before division

q = {'project': project_id,
     'engine': '{"facets":[],"mode":"row-based"}',
     'format': "csv"
    }

# todo 一時的にファイル出力しているので改良の余地あり
r = requests.post(url + '/command/core/export-rows', params=q)
f = open('tmp.csv','w', encoding='utf-8')
f.write(r.text)
f.close()
df = pd.read_csv('tmp.csv')

#print(df)

# get projectname
def get_project_name(project_id):
    res = requests.get(url + '/command/core/get-all-project-metadata')
    data = res.json()
    project_name = data['projects'][str(project_id)]['name']

    return project_name

# create devide dataframe
def devide_dataframe(df, n):
    """ Devide dataframe created from CSV
    df: Dataframe created from CSV
    n: Number of columns to divide
    """
    column_num = len(df.columns)
    sub_df_list = []

    for i in range(0, column_num, n):
        sub_df = df.iloc[0:, i:i+n]
        sub_df_list.append(sub_df)
    
    return sub_df_list

# create OpenRefine project
def create_project(name, df_list):
    """
    ref:https://qiita.com/5zm/items/92cde9e043813e02eb68
    """
    for i in range(0, len(df_list)):
        f_name = str.format('tmp_{}.csv',i)
        p_name = str.format('{}_{}',name,i)
        df_list[i].to_csv(f_name, index=False)
    
        q = {'project-file': f_name,
             'project-name': p_name,
             'format': 'text/line-based/*sv'
            }

        files={'file': open(f_name,'rb')}     
        res = requests.post(url + '/command/core/create-project-from-upload', files=files, params=q)
    
# main
project_name = get_project_name(project_id)
sub_df_list = devide_dataframe(df, 10)
create_project(project_name, sub_df_list)

5. 実行結果

プロジェクトが3つに分割されました。
image.png

まとめ

OpenRefineが1つのデータテーブルに対してデータ整形するツールであるため、データテーブルの分割機能はなさそうです。(OpenRefine APIを使わないで分割できる方法を知っている方は是非ご連絡してください!)

今回のようにGUIで操作できないオペレーションはOpenRefine APIを使って作りこむことができますので、これをモジュール化して、OpenRefineの拡張機能(エクステンション)することができればやってみたいですね。

© 2022 k69

本サイトを通じて、たくさんの人がプログラミングに興味を持ち、 これがキッカケでモノづくりの楽しさに触れることができれば幸せです!