機械学習データ前処理入門

機械学習のためのデータ前処理:数値?文字列?正しいデータ型への変換【Pandas入門】

Tags: データ前処理, Pandas, データ型, Python, 機械学習

はじめに:なぜデータ型が機械学習で重要なのか

機械学習モデルを構築する際、入力となるデータはコンピュータが理解できる形式である必要があります。私たちは普段、Excelなどでデータを見る時に、数値、文字、日付といった違いを直感的に理解していますが、コンピュータ、特に機械学習モデルにとっては、データの「型(タイプ)」が厳密に定義されていることが非常に重要になります。

例えば、「売上高」が数値として入力されるべきところに、誤って「¥1,000」のような文字列としてデータが入っていると、モデルはこれを計算可能な数値として扱えません。また、「顧客の登録日」が日付として扱われるべきなのに、単なる文字列「2023/10/27」として認識されていると、日時の差を計算したり、曜日を抽出したりといった時間に関する分析ができなくなります。

このように、データが本来持つべき型になっていないと、機械学習モデルがデータを正しく解釈・学習できず、結果としてモデルの性能が著しく低下してしまう可能性があります。そのため、データ前処理の初期段階で、データの型を適切に確認し、必要に応じて変換する作業が不可欠となります。

この記事では、Pythonのデータ分析ライブラリであるPandasを使って、データの型を確認し、一般的な型(数値、文字列、日付)への変換を行う方法を分かりやすく解説します。プログラミング経験が少ない方でも理解できるよう、丁寧な説明と具体的なコード例を交えて進めていきます。

データ型の確認方法:dtypes属性

まずは、読み込んだデータがどのような型になっているかを確認することから始めましょう。Pandasでは、DataFrameの dtypes 属性を使うことで、各列のデータ型を一覧で確認できます。

例として、簡単なデータを含むDataFrameを作成してみましょう。

import pandas as pd
import numpy as np

# サンプルデータの作成
data = {
    '商品ID': [101, 102, 103, 104, 105],
    '商品名': ['ノート', 'ペン', '消しゴム', 'ファイル', 'ホッチキス'],
    '価格': ['500', '150', '100', '800', '1200'], # 価格が文字列になっている想定
    '在庫数': [50, 120, 80, 30, 45],
    '登録日': ['2023-01-15', '2023-01-15', '2023-02-01', '2023-02-10', '2023-03-05'], # 日付が文字列になっている想定
    '割引対象': [True, False, True, False, True]
}
df = pd.DataFrame(data)

# データ型を確認
print(df.dtypes)

上記のコードを実行すると、以下のような出力が得られます。

商品ID     int64
商品名    object
価格     object
在庫数      int64
登録日    object
割引対象    bool
dtype: object

出力結果から、商品ID在庫数int64 (整数型)、割引対象bool (真偽値型) と、意図した型になっていることがわかります。しかし、商品名価格登録日object と表示されています。Pandasにおいて object 型は、通常、文字列やPythonの汎用オブジェクトが混在している場合に表示されます。この例では、価格登録日 は本来それぞれ数値や日付として扱いたいデータですが、object 型(文字列として認識されている可能性が高い)になっています。

このように、dtypes を使うことで、データの前処理が必要な列を特定できます。

一般的なデータ型と機械学習での扱い

Pandasでよく遭遇するデータ型はいくつかあります。機械学習モデルは、これらの型を適切に扱える必要があります。

今回のテーマである「型変換」は、主に object 型になっている数値データや日付データを、それぞれ int/floatdatetime64 といった適切な型に変換することを指します。

基本的な型変換:astype() メソッド

Pandasで最も基本的な型変換を行うのが astype() メソッドです。このメソッドを使うと、指定した列(Series)やDataFrame全体のデータ型を指定した型に変換できます。

例えば、先ほどのサンプルデータで 価格 列を数値型に変換してみましょう。本来は整数なので int64 に変換したいところですが、文字列に非数値が含まれていないか保証できない場合は、一時的に浮動小数点数型 (float64) に変換するのが安全です。

# '価格' 列を浮動小数点数型に変換
df['価格'] = df['価格'].astype('float64')

# 型を再度確認
print(df.dtypes)

出力結果:

商品ID     int64
商品名    object
価格     float64 # float64に変換された
在庫数      int64
登録日    object
割引対象    bool
dtype: object

価格 列が float64 に変換されたことが確認できます。これで、価格 を使って計算や数値を用いた機械学習モデルへの入力が可能になります。

もし、変換したい文字列が完全に数値形式(例: "100", "50.5")であれば、int64float64 へ直接変換できます。

注意点:変換できないデータがある場合

astype() は非常に便利ですが、変換できない値(例: 数値型に変換したい列に "N/A" や空文字が含まれている場合)があるとエラーが発生して処理が停止してしまいます。

# エラーを起こす例を想定 (実際にはコメントアウトして実行しない)
# data_error = {'数値になりたい': ['100', '200', 'エラー値', '300']}
# df_error = pd.DataFrame(data_error)
# df_error['数値になりたい'] = df_error['数値になりたい'].astype('float64') # ここでエラーになる

このような場合にどう対処するかは、次のセクションで解説します。

数値への安全な変換:pd.to_numeric()

数値型への変換で、変換できない値が含まれている可能性がある場合は、pd.to_numeric() 関数を使用するのが安全です。この関数には、エラー処理の方法を指定できる errors 引数があります。

errors='coerce' オプションは、データクレンジングと型変換を同時に行えるため非常によく使われます。変換できなかった非数値データが欠損値として扱われるため、その後の欠損値処理(補完や削除など)に繋げやすくなります。

先ほどのサンプルデータで、もし 価格 列に数値以外のデータが含まれていた場合を想定し、pd.to_numeric() を使って安全に変換してみましょう。ここでは、サンプルデータには非数値は含まれていませんが、コードの書き方として示します。

# '価格' 列を数値型に変換(変換できない場合はNaNに置き換え)
df['価格'] = pd.to_numeric(df['価格'], errors='coerce')

# 型を再度確認
print(df.dtypes)
# 欠損値ができたか確認 (今回はならない想定だが、データによってはNaNが生成される)
print(df.isnull().sum())

出力結果:

商品ID     int64
商品名    object
価格     float64 # 数値型に変換される
在庫数      int64
登録日    object
割引対象    bool
dtype: object

商品ID    0
商品名     0
価格      0 # 今回のサンプルデータでは欠損値は生成されない
在庫数     0
登録日     0
割引対象    0
dtype: int64

pd.to_numeric() を使用すると、価格 列が float64 型に変換されます。もし非数値データが含まれていれば、その箇所は NaN となり、isnull().sum()で確認した際に表示されるようになります。

日付時刻型への変換:pd.to_datetime()

日付や時刻に関するデータは、多くの場合、ファイルから読み込むと文字列(object 型)として扱われます。これを日付時刻型 (datetime64) に変換することで、時間に基づいた分析が可能になります。Pandasでは pd.to_datetime() 関数を使用します。

先ほどのサンプルデータで 登録日 列を日付時刻型に変換してみましょう。

# '登録日' 列を日付時刻型に変換
df['登録日'] = pd.to_datetime(df['登録日'])

# 型を再度確認
print(df.dtypes)

出力結果:

商品ID             int64
商品名             object
価格             float64
在庫数              int64
登録日    datetime64[ns] # 日付時刻型に変換された
割引対象              bool
dtype: object

登録日 列が datetime64[ns] 型に変換されました。これで、この列から年、月、日、曜日などを抽出したり、他の日付との差を計算したりといった操作が可能になります。

pd.to_datetime() も、変換できない文字列が含まれている場合や、日付の形式が混在している場合にエラーが発生することがあります。このような場合にも、errors='coerce' オプションが有効です。変換できなかったデータは NaT (Not a Time、欠損値) に置き換えられます。

# 変換できない日付文字列が含まれていた場合を想定
# df['登録日'] = pd.to_datetime(df['登録日'], errors='coerce')

# 変換後の確認 (データによってはNaTが生成される)
# print(df['登録日'].isnull().sum())

また、pd.to_datetime() は様々な日付形式を自動的に判別してくれますが、特定の形式を指定したい場合は format 引数を使用することも可能です(例: format='%Y/%m/%d')。

型変換後の確認と次のステップ

データ型の変換は、データ前処理の他のステップと密接に関連しています。

型変換が意図通りに行われたかは、必ず df.dtypes を使って確認しましょう。また、変換後に欠損値が発生していないかも df.isnull().sum() などで確認することが重要です。

まとめ

この記事では、機械学習のためのデータ前処理におけるデータ型の重要性と、Pandasを使った基本的な型変換の方法を解説しました。

データ型を適切に整えることは、機械学習プロジェクトを成功させるための最初の、そして非常に重要なステップの一つです。この記事を参考に、お手元のデータでぜひ型変換を試してみてください。

データ前処理には様々な手法があり、本サイトではそれらを体系的に学ぶための記事を提供していきます。引き続き、他の記事も参考にしていただければ幸いです。