💡

chatGPTによるデータの自動前処理プロンプトが機能するか試してみた

2023/04/18に公開

データサイエンティストの仕事をしていると、データの前処理に工数がかかってしまうことがよくあります。
この記事で説明しているようにデータ解析の業務の8割は前処理をしていると言っても過言ではありません。

https://xtech.nikkei.com/atcl/learning/lecture/19/00110/00001/

なぜそんなことが起こるかというと、データ解析者はよくこういうデータに出会うことがあるからです。

性別 年齢 住所 仕事以外の学習時間
female 23才 東京都港区 30分
male 32歳 埼玉県 1時間半
無回答 29 大阪 2分

ご覧の通り、各カラムがバラバラです。
性別はmale(男性)とfemale(女性)と無回答があり、文字ではデータ解析できないので、数値に直す必要があります。

年齢は「才」や「歳」という字が入っていたり、ただの数字が入っていたりとバラバラです。

住所は、東京は区まで入っているし、埼玉は「県」まで入っているが、大阪は「府」が入ってないです。

そして、仕事以外の学習時間は、時間と分の単位がバラバラです。

今まであれば、一つ一つのカラムをどう前処理すれば良いかを考えて、以下のようなコードを書く必要がありました。

# 性別をダミーデータに変換
df['性別'] = df['性別'].map({'female': 1, 'male': 0, '無回答': np.nan})

# 年齢を数値に変換
df['年齢'] = df['年齢'].str.extract('(\d+)').astype(int)

# 仕事以外の学習時間を分数に変換
def convert_to_minutes(time_str):
    hours = 0
    minutes = 0
    if '時間' in time_str:
        hours = int(time_str.split('時間')[0])
        time_str = time_str.split('時間')[1]
    if '分' in time_str:
        minutes = int(time_str.split('分')[0])
    total_minutes = hours * 60 + minutes
    return total_minutes

df['仕事以外の学習時間'] = df['仕事以外の学習時間'].apply(convert_to_minutes)


def extract_prefecture(address):
    # 都道府県名の正規表現パターン
    pattern = r'(北海道|青森県|岩手県|宮城県|秋田県|山形県|福島県|茨城県|栃木県|群馬県|埼玉県|千葉県|東京都|神奈川県|新潟県|富山県|石川県|福井県|山梨県|長野県|岐阜県|静岡県|愛知県|三重県|滋賀県|京都府|大阪府|兵庫県|奈良県|和歌山県|鳥取県|島根県|岡山県|広島県|山口県|徳島県|香川県|愛媛県|高知県|福岡県|佐賀県|長崎県|熊本県|大分県|宮崎県|鹿児島県|沖縄県)'
    match = re.search(pattern, address)
    if match:
        return match.group(1)
    else:
        return None

# 住所カラムの都道府県だけを抽出
df['住所'] = df['住所'].apply(extract_prefecture)

上記の処理をデータに対してすることで、以下のような綺麗なデータにすることができます。

性別 年齢 住所 仕事以外の学習時間
1.0 23 東京都 30
0.0 32 埼玉県 90
NaN 29 大阪府 2

しかし、ここまで来るのに結構な工数がかかると思いませんか?

これをプロンプトで、文章で指示が出せるかを試してみました。
以下のようなプロンプトを作成し、chatGPTのAPIを使ってデータを入力してみました。

これはデータの前処理をするプロンプトです。データを以下の処理に従って辞書型で返してください。
性別をダミーデータに変換: 'male'を0、'female'を1、'無回答'を欠損値(例:np.nan)に変換します。
年齢を数値に変換: "才"や"歳"を取り除き、数値に変換します。
仕事以外の学習時間を分数に変換: 文字列を分と時間に分解し、すべて分単位に変換します。
都道府県のみに変換します。
data = [
    {"性別": "female", "年齢": "23才", "住所": "東京都港区", "仕事以外の学習時間": "30分"},
    {"性別": "male", "年齢": "32歳", "住所": "埼玉県", "仕事以外の学習時間": "1時間半"},
    {"性別": "無回答", "年齢": "29", "住所": "大阪", "仕事以外の学習時間": "2分"},
]

messages =[
        {"role": "system", "content":f"これはデータの前処理をするプロンプトです。データを以下の処理に従って辞書型で返してください。性別をダミーデータに変換: 'male'を0、'female'を1、'無回答'を欠損値(例:np.nan)に変換します。年齢を数値に変換: 「才」や「歳」を取り除き、数値に変換します。都道府県のみに変換します。仕事以外の学習時間を分数に変換: 文字列を分と時間に分解し、すべて分単位に変換します。{data[0]}"}
    ]

response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages)

print(response["choices"][0]["message"]["content"]) 

とすると結果はなんと、、、

{
    '性別': 1,
    '年齢': 23,
    '住所': '東京都',
    '仕事以外の学習時間': 30
}

おおお!ちゃんと前処理されています!
2つ目も3つ目もきちんと前処理されています!

{
    '性別': 0,
    '年齢': 32,
    '住所': '埼玉県',
    '仕事以外の学習時間': 90
}

{
    '性別': NaN,
    '年齢': 29,
    '住所': '大阪府',
    '仕事以外の学習時間': 2
}


問題は処理時間が結構かかってしまうので、大量のデータだと、やはりPythonのコードを使った方が早いと思います。

ただ、自然文でプログラミング・前処理ができることが確認することができ、これまで多くの工数がかかってきたデータ解析を行う上での前処理が効率化できるかもしれない可能性を見出すことができました。

Discussion