ども、k69 です。
OpenRefineというデータ整形(データ前処理)ツールで「データ分割」をやってみました。
OpenRefineのGUIではテーブル分割(1つのプロジェクトを複数に分割)する機能を見つけることができなかったので、pythonでOpenRefine APIを呼び出してデータ分割をやってみました。
他にもいろいろなパターンを試しているので
「【まとめ】OpenRefineの使い方をまとめていく」も参考にしてください。
「データ分割」について説明
ここではプロジェクト(データテーブル)を10カラム(列)ごとに分割し、新規プロジェクトを作成しOpenRefineに登録します。
データ整形前
29カラム(列)の1つのプロジェクトの状態です。
データ整形後
10,10,9カラム(列)の3プロジェクトに分割されます。
OpenRefineでデータ整形する手順
では、さっそくOpenRefine APIで操作してみましょう。
データの取り込み
データダウンロード
CSVデータはこちら(右クリック→名前を付けてリンク先を保存)からダウンロードできます。
OpenRefineにCSVデータ取り込み
1. ダウンロードしたファイルを選択し、Next を押下します
2. 文字化けした場合はUTF-8を設定します
3. プロジェクトを作成します
プロジェクトを作成したときにプロジェクト番号が作成されるので、ブラウザのURLに表示される番号をメモしておきます。
4. Jpyter Notebook などで下記のpythonコードを実行します。
★ の部分は環境に合わせてください
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つに分割されました。
まとめ
OpenRefineが1つのデータテーブルに対してデータ整形するツールであるため、データテーブルの分割機能はなさそうです。(OpenRefine APIを使わないで分割できる方法を知っている方は是非ご連絡してください!)
今回のようにGUIで操作できないオペレーションはOpenRefine APIを使って作りこむことができますので、これをモジュール化して、OpenRefineの拡張機能(エクステンション)することができればやってみたいですね。