kimetu
@kimetu (sho)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

python 機械学習における誤入力データの処理方法 

解決したいこと

数値データ内に含まれる文字データの処理方法

pythonでホテルの価格予測データの分析の練習をしている際、
数値列にも関わらず、文字データが入力されておりmatplotによる図示化や
機械学習が行えていない状況です。

以下のようにホテル価格のとこに煙探知機などの単語が誤入力されています。

発生している問題・エラー

ValueError: invalid literal for int() with base 10: 'Smoke detector""'

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
tryでエラーの行番号の取得を試みましたが途中で止まってしまうのと、
エラーの番号を参照しても数値データで問題ないという結果です。

count = -1
error_box = []
try:
for word in train_data["y"]:
word = int(word)
count += 1
except ValueError:
error_box.append(count)

print(error_box)

0

3Answer

word = int(word)の箇所でエラーになりますので、そこで引っかかった時点でExceptの方に処理が移り問題の行ではcount += 1が実行されないので、error_boxの変数に入っている番号の次の行(+1した行)を見るなどの対応が必要になると思われます!

countが-1からスタートしているため、行番号が1からカウントされている場合は次の次の行(+2した行)の確認が必要になるかなと。Pandasなどで0からのスタートのインデックスやリストのインデックスで参照している場合は+1で大丈夫かなと思われます!

1Like

Comments

  1. @kimetu

    Questioner

    ありがとうございます!!
    6時間ぐらい取り組んでいてまったく進んでいませんでした。
    うまくいかない理由がわかりました!

    数値の列に欠損値と文字が誤記入されている場合、どのように処理すればよいか
    教えて頂きたいです。
    kaggle等でひたすら調べましたがうまくいかない状況です。
    お手数をお掛けしますが、何卒ご教授の程よろしくお願いします。

私の方がKaggleには詳しくない感じではありますが、色々方法(方針)があると思われます!

例えば、

  • 不正なデータの行数が少ないのであればその行を削除してしまう
  • 不正なデータの列部分はそれなりにあるものの、他の列のデータは正常なデータが入っていたりで行の削除してしまうと学習データが結構減ってしまって適切ではない・・・といった場合には他の行の値の平均や中央値で補完する

など色々な方法があると思います!

説明のために以下のようなtrain_dataというデータフレームがあると想定して進めます!(コード見ていた感じ、train_dataという変数がデータフレームかな?と思いましたが、もし違っておりましたらご容赦ください)

サンプルとしてxは適当な値を設定しています。2行目のyが不正な文字列、3行目が欠損値としています。

import pandas as pd
import numpy as np

train_data = pd.DataFrame(
    data=[{
        'x': 1,
        'y': 10,
    }, {
        'x': 2,
        'y': 'Smoke detector',
    }, {
        'x': 3,
        'y': np.nan,
    }, {
        'x': 4,
        'y': 11,
    }])
print(train_data)
   x              y
0  1             10
1  2  Smoke detecto
2  3            NaN
3  4             11

不正なデータの行を削除したいのであれば、こちらもコードの書き方が色々あると思いますが一例として以下のようなもので対応ができると思われます!

import pandas as pd
import numpy as np

train_data = pd.DataFrame(
    data=[{
        'x': 1,
        'y': 10,
    }, {
        'x': 2,
        'y': 'Smoke detecto',
    }, {
        'x': 3,
        'y': np.nan,
    }, {
        'x': 4,
        'y': 11,
    }])

def is_valid(y):
    try:
        int(y)
    except Exception:
        return False
    return True

train_data['is_valid'] = train_data['y'].apply(is_valid)
train_data = train_data[train_data['is_valid']]
del train_data['is_valid']
print(train_data)

整数変換ができる行(1行目と4行目)のみ残ります。

   x   y
0  1  10
3  4  11

コードの説明ですが、まずyの値(整数や欠損値などを受け付けます)を引数に取る関数(is_valid)を設けまして、もし正常に整数変換(int(y))ができる場合にはTrue、変換ができずエラーになる場合にはFalseを返却するようにしてあります。

続いてデータフレームのapplyメソッドを使って作ったis_valid関数をデータフレームに反映します(train_data['y'].apply(is_valid)部分)。返却値はSeries(今回は列のデータ)となるため、そちらをtrain_data['is_valid']といった感じにis_validという列に設定しています。

※applyメソッドなどについては以下の記事などをご参照ください。

この時点でtrain_dataの中身は以下のようになっています!

   x              y  is_valid
0  1             10      True
1  2  Smoke detecto     False
2  3            NaN     False
3  4             11      True

続いてis_validの列がTrueの行のみ残せばよいので、train_data = train_data[train_data['is_valid']]といった感じで指定してスライスを行っています。
このあたりの制御の詳細は必要に応じて以下の記事などをご確認ください。

最後にdel train_data['is_valid']として、不要になったis_valid列を削除しています!

※欠損値などの行を削除するのではなく、中央値やもしくは他の任意の値で補正したい場合は事前にその埋めたい値を算出しておいて、同じ感じでapplyメソッドなどを使うと実現できると思います!

例えば一例として以下のようなコードになるかなと思います。

import pandas as pd
import numpy as np

train_data = pd.DataFrame(
    data=[{
        'x': 1,
        'y': 10,
    }, {
        'x': 2,
        'y': 'Smoke detecto',
    }, {
        'x': 3,
        'y': np.nan,
    }, {
        'x': 4,
        'y': 11,
    }])

fill_value = 10.5

def is_valid(y):
    try:
        int(y)
    except Exception:
        return fill_value
    return y

train_data['y'] = train_data['y'].apply(is_valid)
print(train_data)

fill_valueという値が不正な値に設定したい任意の値としています(今回は直接値を設定していますが、必要に応じて中央値などに調整ください)。

applyメソッドでもし整数変換が正常にできるのであればyの値をそのまま返却、もし変換ができない不正な値であればfill_valueを返却しています!

実行してみると以下のように補正されます!

   x     y
0  1  10.0
1  2  10.5
2  3  10.5
3  4  11.0
1Like

詳しく教えて頂きありがとうございます!

記載の通りに読み進めて内容理解できました!

教えて頂いたおかげで勉強がんばれそうです。
本当にありがとうございました。

0Like

Your answer might help someone💌