【Pandas】外れ値を除去したり、置換する方法[Python]

  • URLをコピーしました!
目次

Pandas

前回、Biopythonで2本の遺伝子やタンパク質の配列間の比較(ペアワイズアライメント)をする方法を紹介しました。

今回はPandasの話題で外れ値を除去したり、置換する方法を紹介します。

それでは始めていきましょう。

外れ値をもったデータを作成するプログラム

まずは外れ値をもったデータが必要なので、そんなデータを作成するプログラムを作ってみました。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

print(df)
print(df.plot.scatter(x="x", y="y"))

実行結果
     x          y
0    0  13.808903
1    1  19.497257
2    2  17.332677
3    3  18.519145
4    4  14.609500
..  ..        ...
95  95  13.393565
96  96  18.504409
97  97  17.751455
98  98  17.368624
99  99  10.373463

[100 rows x 2 columns]
Axes(0.125,0.11;0.775x0.77)

プログラムの概要としては「num = データ数」、「val_range = [値1, 値2]」で外れ値以外の値の範囲、「outlier_val = 外れ値」を設定します。

すると「outlier_num」で外れ値となるデータ番号が設定され、for文で値の設定、最後のPandasのデータフレームに格納しているという感じです。

ちなみに今後、さまざまな値が出てきますが、このプログラムの性質上、外れ値以外の値はランダムなので、毎回違いがあることに注意してください。

データ全体の確認:.describe()

まずデータの中に外れ値があるかどうかを確認します。

先ほどのようにプロットするのも一つの手ですし、データの統計値を見るもの一つの手です。

データの統計値を見るには「データフレーム.describe()」を使います。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

print(df.describe())

実行結果
                x            y
count  100.000000   100.000000
mean    49.500000    24.594459
std     29.011492    98.573970
min      0.000000    10.179754
25%     24.750000    11.762006
50%     49.500000    14.415880
75%     74.250000    17.636297
max     99.000000  1000.000000

countはデータ数、meanは平均値、stdは標準偏差、minは最小値、25%は最小値から数えて25%となる値、50%は最小値から数えて50%となる値が、75%は最小値から数えて75%となる値、maxは最大値です。

ちなみに25%、50%、75%は四分位数と呼ばれ、それぞれ25パーセンタイル(第一四分位数)、50パーセンタイル(第二四分位数)、75パーセンタイル(第三四分位数)とよ呼びます。

データの統計値を始め、概要を見る方法はこちらの記事で紹介していますので、よかったらどうぞ。

この統計値からすると平均値が「24.594459」になっている、また75%が「17.636297」にも関わらず、最大値が「1000」となっているので、外れ値があることが分かります。

外れ値の取得

次に外れ値となる値を取得していきます。

ここでまず使用するのが「.quantile(値)」です。

先ほどの統計値では四分位数(25パーセンタイル、50パーセンタイル、75パーセンタイル)が出てきましたが、「.quantile(値)」を使うと好きなパーセンタイルとなる値を取得できます。

値は0から1の間で指定します。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

quantile9 = df["y"].quantile(0.9)

print(quantile9)

実行結果
18.55377984990959

これで90パーセンタイルの値は「18.55377984990959」であると分かりました。

この値を使って、この値以上、つまり外れ値の候補となる値を抽出してみます。

特定の値以上の値をもつデータを抽出するには「df[df[“列”] >= 値]」とします。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

quantile9 = df["y"].quantile(0.9)

df_outlier = df[df["y"] >= quantile9]

print(df_outlier)

実行結果
     x            y
3    3    19.725857
6    6    19.374549
13  13    19.337465
24  24    19.865614
48  48    19.510822
49  49    18.860829
52  52    19.919411
83  83    19.419082
92  92  1000.000000
97  97    18.785923

今回100個のデータを準備していて、90パーセンタイルを指定しているので、残りの10%、つまり10個のデータが抽出できました。

ただここで外れ値の対象となるのは1個ですので、99パーセンタイルにしてみましょう。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

quantile99 = df["y"].quantile(0.99)

df_outlier = df[df["y"] >= quantile99]

print(df_outlier)
print(df_outlier.index.tolist())

実行結果
     x       y
77  77  1000.0
[77]

毎回、データの作成から行なっているので、インデックスが違っていますが、とりあえず外れ値のみを抽出できました。

外れ値のデータを削除する方法

次に外れ値となるデータを削除してみましょう。

先ほどまでに外れ値となる行のインデックスが取得できているので、「データフレーム.drop(インデックス)」で外れ値となるデータの行を削除します。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

quantile99 = df["y"].quantile(0.99)

df_outlier = df[df["y"] >= quantile99]

df = df.drop(df_outlier.index.tolist())

print(df.describe())

               x          y
count  99.000000  99.000000
mean   49.848485  14.604640
std    28.948005   2.777397
min     0.000000  10.119776
25%    25.500000  12.472751
50%    50.000000  14.006469
75%    74.500000  16.614206
max    99.000000  19.969853

データが一つ減ったので、count(データ数)が100から99に一つ減っています。

またmax(最大値)が19.969853となり、飛び抜けて大きな値が無くなったことが分かります。

外れ値を置換する方法

次に外れ値を置換する方法を紹介します。

今回は外れ値以外の平均値に置換することにします。

まず外れ値以外のデータを取得するのに「df_normal = df[df[“x”] < quantile99]」とします。

そして得られたデータの平均値を「average = df_normal[“y”].mean()」で取得する。

そしてその値を使って行と列を指定して値を書き換えるということをします。

ということでこんな感じ。

import random
import pandas as pd

num = 100
val_range = [10, 20]
outlier_val = 1000

outlier_num = random.randrange(num)

val_list = []
for i in range(num):
    if i == outlier_num:
        val_list.append([i, outlier_val])
    else:
        val_list.append([i, random.uniform(val_range[0], val_range[1])])

df = pd.DataFrame(val_list, columns=["x", "y"])

quantile99 = df["y"].quantile(0.99)

df_normal = df[df["x"] < quantile99]
average = df_normal["y"].mean()

df_outlier = df[df["y"] >= quantile99]

outlier_num = df_outlier.index.tolist()

for num in outlier_num:
    print(df["y"].iloc[num])
    df.iloc[num, 1] = average
    print(df["y"].iloc[num])

print(df.describe())

実行結果
1000.0
15.034219088827172
                x           y
count  100.000000  100.000000
mean    49.500000   14.640517
std     29.011492    2.698875
min      0.000000   10.013275
25%     24.750000   12.633835
50%     49.500000   14.086224
75%     74.250000   16.839727
max     99.000000   19.999720

「df.iloc[num, 1] = average」が値を書き換えている部分です。

その証拠にその前後で「print(df[“y”].iloc[num])」と値を表示させてみると、置換前は「1000」、置換後は「15.034219088827172」となっています。

ということで値を書き換えることもできました。

ただ今回、データを削除するdropや値を書き換える方法はさらっと紹介しただけなので、次回とその次の記事でそれぞれもう少し詳しく紹介します。

ということで次回はPandasで特定の値をもつデータを削除する方法を紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次