ウェブサイト検索

Python を使用して機械学習のデータ クリーニングを実行する方法


データ クリーニングは、あらゆる機械学習プロジェクトにおいて非常に重要なステップです。

表形式データには、実行する必要のあるデータ クリーニング操作を特定するためにデータを調査するために使用できる、さまざまな統計分析およびデータ視覚化手法が多数あります。

高度な方法に進む前に、すべての機械学習プロジェクトで実行する必要がある非常に基本的なデータ クリーニング操作がいくつかあります。これらは非常に基本的なため、熟練した機械学習の実践者によって見落とされがちですが、非常に重要であるため、スキップするとモデルが壊れたり、過度に楽観的なパフォーマンス結果を報告したりする可能性があります。

このチュートリアルでは、データセットに対して常に実行する必要がある基本的なデータ クリーニングについて説明します。

このチュートリアルを完了すると、次のことがわかります。

  • 値が 1 つだけある列変数を特定して削除する方法。
  • 一意の値がほとんどない列変数を識別して考慮する方法。
  • 重複した観測値を含む行を特定して削除する方法。

私の新しい本『Data Preparation for Machine Learning』 でプロジェクトをキックスタートします。これにはステップバイステップのチュートリアルPython ソース コード ファイルが含まれています。すべての例。

始めましょう。

  • 2020 年 4 月更新: データセットと VarianceThreshold に関するセクションを追加しました。
  • 2020 年 5 月更新: 引用と参考書籍を追加しました。

チュートリアルの概要

このチュートリアルは 7 つの部分に分かれています。彼らです:

  1. 乱雑なデータセット
  2. 単一の値を含む列を特定する
  3. 単一の値を含む列を削除する
  4. 値がほとんどない列を考慮する
  5. 分散が低い列を削除する
  6. 重複データを含む行を特定する
  7. 重複データを含む行を削除する

乱雑なデータセット

データ クリーニングとは、予測モデルに悪影響を与える可能性のあるデータセット内のエラーを特定して修正することを指します。

データ クリーニングは、データ内のエラーを検出して修復するためのあらゆる種類のタスクやアクティビティを指すために使用されます。

— xiii ページ、データ クリーニング、2019 年。

データ クリーニングは非常に重要ではありますが、複雑なテクニックを必要とするわけではありません。データセットに関する十分な知識が必要です。

データのクリーンアップは最も華やかなタスクではありませんが、データ ラングリングの重要な部分です。 […] データを適切にクリーニングして組み立てる方法を知っていれば、その分野の他の人と大きく差をつけることができます。

— 149 ページ、Python によるデータ ラングリング、2016 年。

データセットには多くの種類のエラーが存在しますが、最も単純なエラーには、情報があまり含まれていない列や重複した行が含まれます。

乱雑なデータの特定と修正に入る前に、いくつかの乱雑なデータセットを定義しましょう。

このチュートリアルの基礎として、油流出データセットアヤメの花データセットという 2 つのデータセットを使用します。

油流出データセット

いわゆる「石油流出」データセットは、標準的な機械学習データセットです。

このタスクには、パッチに油流出が含まれているかどうかを予測することが含まれます。衛星画像のパッチの内容を記述するベクトルを指定すると、海洋への石油の不法投棄または偶発的投棄からの結果が得られます。

937件あります。各ケースは、コンピューター ビジョンから派生した 48 個の数値特徴、パッチ番号、およびクラス ラベルで構成されます。

通常のケースは、油流出なしでクラス ラベル 0 が割り当てられますが、油流出はクラス ラベル 1 で示されます。油流出なしのケースが 896 件、油流出のケースが 41 件あります。

ここからデータセット全体にアクセスできます。

  • 油流出データセット (oil-spill.csv)
  • 油流出データセットの説明 (oil-spill.names)

ファイルの内容を確認します。

ファイルの最初の数行は次のようになります。

1,2558,1506.09,456.63,90,6395000,40.88,7.89,29780,0.19,214.7,0.21,0.26,0.49,0.1,0.4,99.59,32.19,1.84,0.16,0.2,87.65,0,0.47,132.78,-0.01,3.78,0.22,3.2,-3.71,-0.18,2.19,0,2.19,310,16110,0,138.68,89,69,2850,1000,763.16,135.46,3.73,0,33243.19,65.74,7.95,1
2,22325,79.11,841.03,180,55812500,51.11,1.21,61900,0.02,901.7,0.02,0.03,0.11,0.01,0.11,6058.23,4061.15,2.3,0.02,0.02,87.65,0,0.58,132.78,-0.01,3.78,0.84,7.09,-2.21,0,0,0,0,704,40140,0,68.65,89,69,5750,11500,9593.48,1648.8,0.6,0,51572.04,65.73,6.26,0
3,115,1449.85,608.43,88,287500,40.42,7.34,3340,0.18,86.1,0.21,0.32,0.5,0.17,0.34,71.2,16.73,1.82,0.19,0.29,87.65,0,0.46,132.78,-0.01,3.78,0.7,4.79,-3.36,-0.23,1.95,0,1.95,29,1530,0.01,38.8,89,69,1400,250,150,45.13,9.33,1,31692.84,65.81,7.84,1
4,1201,1562.53,295.65,66,3002500,42.4,7.97,18030,0.19,166.5,0.21,0.26,0.48,0.1,0.38,120.22,33.47,1.91,0.16,0.21,87.65,0,0.48,132.78,-0.01,3.78,0.84,6.78,-3.54,-0.33,2.2,0,2.2,183,10080,0,108.27,89,69,6041.52,761.58,453.21,144.97,13.33,1,37696.21,65.67,8.07,1
5,312,950.27,440.86,37,780000,41.43,7.03,3350,0.17,232.8,0.15,0.19,0.35,0.09,0.26,289.19,48.68,1.86,0.13,0.16,87.65,0,0.47,132.78,-0.01,3.78,0.02,2.28,-3.44,-0.44,2.19,0,2.19,45,2340,0,14.39,89,69,1320.04,710.63,512.54,109.16,2.58,0,29038.17,65.66,7.35,0
...

最初の列にパッチ番号の整数が含まれていることがわかります。また、コンピューター ビジョンから派生した特徴が、2 番目の列では千の位、他の列では分数など、さまざまなスケールで実数値が表現されていることもわかります。

このデータセットには、データ クリーニングの適切な基礎となる一意の値がほとんど含まれない列が含まれています。

アイリスの花のデータセット

いわゆる「アイリスの花」データセットも、標準的な機械学習データセットです。

このデータセットには、アヤメの花のセンチメートル単位の測定値から花の種類を予測することが含まれています。

これは複数クラスの分類問題です。各クラスの観測値の数はバランスが取れています。 4 つの入力変数と 1 つの出力変数を含む 150 の観測値があります。

ここからデータセット全体にアクセスできます。

  • アイリスの花データセット (iris.csv)
  • アイリスの花のデータセットの説明 (iris.names)

ファイルの内容を確認します。

ファイルの最初の数行は次のようになります。

5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
...

4 つの入力変数はすべて数値であり、ターゲット クラス変数はアイリスの花の種類を表す文字列であることがわかります。

このデータセットには重複行が含まれており、データ クリーニングの適切な基礎となります。

単一の値を含む列を特定する

単一の観測値または値を含む列は、おそらくモデリングには役に立ちません。

これらの列または予測子は、分散 (平均からの平均値) を測定するとゼロになるため、ゼロ分散予測子と呼ばれます。

予測子に単一の値が含まれている場合、予測子によって実際には変動が表示されないため、これをゼロ分散予測子と呼びます。

— 96 ページ、特徴エンジニアリングと選択、2019 年。

ここで、単一の値は、その列の各行が同じ値を持つことを意味します。たとえば、列 X1 の値は、データセット内のすべての行で 1.0 です。

X1
1.0
1.0
1.0
1.0
1.0
...

すべての行に対して単一の値を持つ列には、モデリングのための情報が含まれません。

データ準備およびモデリング アルゴリズムの選択によっては、単一の値を持つ変数によってエラーや予期しない結果が発生する可能性もあります。

各列の一意の値の数を報告する unique() NumPy 関数を使用して、このプロパティを持つ行を検出できます。

以下の例では、50 個の変数を含む油流出分類データセットを読み込み、各列の一意の値の数を要約します。

# summarize the number of unique values for each column using numpy
from urllib.request import urlopen
from numpy import loadtxt
from numpy import unique
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
data = loadtxt(urlopen(path), delimiter=',')
# summarize the number of unique values in each column
for i in range(data.shape[1]):
	print(i, len(unique(data[:, i])))

この例を実行すると、URL からデータセットが直接ロードされ、各列の一意の値の数が出力されます。

列インデックス 22 には値が 1 つしかないため、削除する必要があることがわかります。

0 238
1 297
2 927
3 933
4 179
5 375
6 820
7 618
8 561
9 57
10 577
11 59
12 73
13 107
14 53
15 91
16 893
17 810
18 170
19 53
20 68
21 9
22 1
23 92
24 9
25 8
26 9
27 308
28 447
29 392
30 107
31 42
32 4
33 45
34 141
35 110
36 3
37 758
38 9
39 9
40 388
41 220
42 644
43 649
44 499
45 2
46 937
47 169
48 286
49 2

より簡単なアプローチは、面倒な作業を自動的に実行してくれる nunique() Pandas 関数を使用することです。

以下は、Pandas 関数を使用した同じ例です。

# summarize the number of unique values for each column using numpy
from pandas import read_csv
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
df = read_csv(path, header=None)
# summarize the number of unique values in each column
print(df.nunique())

この例を実行すると、同じ結果、列インデックス、および各列の一意の値の数が得られます。

0     238
1     297
2     927
3     933
4     179
5     375
6     820
7     618
8     561
9      57
10    577
11     59
12     73
13    107
14     53
15     91
16    893
17    810
18    170
19     53
20     68
21      9
22      1
23     92
24      9
25      8
26      9
27    308
28    447
29    392
30    107
31     42
32      4
33     45
34    141
35    110
36      3
37    758
38      9
39      9
40    388
41    220
42    644
43    649
44    499
45      2
46    937
47    169
48    286
49      2
dtype: int64

単一の値を含む列を削除する

単一の値を持つ変数または列は、おそらくデータセットから削除する必要があります。

… ゼロ分散予測変数を削除するだけです。

— 96 ページ、特徴エンジニアリングと選択、2019 年。

NumPy 配列または Pandas DataFrame から列を削除するのは比較的簡単です。

1 つのアプローチは、単一の一意の値を持つすべての列を記録し、drop() 関数を呼び出して Pandas DataFrame からそれらの列を削除することです。

完全な例を以下に示します。

# delete columns with a single unique value
from pandas import read_csv
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
df = read_csv(path, header=None)
print(df.shape)
# get number of unique values for each column
counts = df.nunique()
# record columns to delete
to_del = [i for i,v in enumerate(counts) if v == 1]
print(to_del)
# drop useless columns
df.drop(to_del, axis=1, inplace=True)
print(df.shape)

この例を実行すると、まずデータセットがロードされ、行と列の数がレポートされます。

各列の一意の値の数が計算され、単一の一意の値を持つ列が識別されます。この場合、列インデックスは 22 です。

次に、識別された列が DataFrame から削除され、DataFrame 内の行と列の数がレポートされて変更が確認されます。

(937, 50)
[22]
(937, 49)

値がほとんどない列を考慮する

前のセクションでは、サンプル データセット内の一部の列には一意の値がほとんどないことがわかりました。

たとえば、2、4、および 9 個の一意の値のみを持つ列がありました。これは、順序変数またはカテゴリ変数の場合には意味があるかもしれません。この場合、データセットには数値変数のみが含まれます。したがって、列内に 2、4、または 9 個の一意の数値しかないのは驚くべきことかもしれません。

これらの列または予測子は、分散がゼロではなく、ゼロに近い非常に小さな数であるため、ゼロに近い分散予測子と呼ぶことができます。

… ゼロに近い分散予測子、またはリサンプリング プロセス中に分散がほぼゼロになる可能性があります。これらは、一意の値がほとんどなく (バイナリ ダミー変数の 2 つの値など)、データ内で頻繁に発生しない予測子です。

— 96 ~ 97 ページ、特徴エンジニアリングと選択、2019 年。

これらの列は、モデルのスキルに寄与する場合もあれば、寄与しない場合もあります。それらがモデリングに役に立たないとは考えられません。

ゼロに近い分散予測子には価値のある予測情報がほとんど含まれていない可能性がありますが、これらをフィルターで除外したくない場合もあります。

— 97 ページ、特徴エンジニアリングと選択、2019 年。

データ準備およびモデリング アルゴリズムの選択によっては、数値が非常に少ない変数によってエラーや予期しない結果が発生する可能性もあります。たとえば、データの準備にべき乗変換を使用するときや、「合理的な」データ確率分布を仮定する線形モデルを当てはめるときに、それらがエラーを引き起こすのを私は見てきました。

このタイプの列を強調表示しやすくするために、各変数の一意の値の数をデータセット内の総行数に対するパーセンテージとして計算できます。

NumPy を使用してこれを手動で実行してみましょう。完全な例を以下に示します。

# summarize the percentage of unique values for each column using numpy
from urllib.request import urlopen
from numpy import loadtxt
from numpy import unique
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
data = loadtxt(urlopen(path), delimiter=',')
# summarize the number of unique values in each column
for i in range(data.shape[1]):
	num = len(unique(data[:, i]))
	percentage = float(num) / data.shape[0] * 100
	print('%d, %d, %.1f%%' % (i, num, percentage))

この例を実行すると、列インデックスと各列の一意の値の数に続いて、データセット内のすべての行の一意の値の割合がレポートされます。

ここでは、一部の列の一意の値の割合が非常に低い (1% 未満など) ことがわかります。

0, 238, 25.4%
1, 297, 31.7%
2, 927, 98.9%
3, 933, 99.6%
4, 179, 19.1%
5, 375, 40.0%
6, 820, 87.5%
7, 618, 66.0%
8, 561, 59.9%
9, 57, 6.1%
10, 577, 61.6%
11, 59, 6.3%
12, 73, 7.8%
13, 107, 11.4%
14, 53, 5.7%
15, 91, 9.7%
16, 893, 95.3%
17, 810, 86.4%
18, 170, 18.1%
19, 53, 5.7%
20, 68, 7.3%
21, 9, 1.0%
22, 1, 0.1%
23, 92, 9.8%
24, 9, 1.0%
25, 8, 0.9%
26, 9, 1.0%
27, 308, 32.9%
28, 447, 47.7%
29, 392, 41.8%
30, 107, 11.4%
31, 42, 4.5%
32, 4, 0.4%
33, 45, 4.8%
34, 141, 15.0%
35, 110, 11.7%
36, 3, 0.3%
37, 758, 80.9%
38, 9, 1.0%
39, 9, 1.0%
40, 388, 41.4%
41, 220, 23.5%
42, 644, 68.7%
43, 649, 69.3%
44, 499, 53.3%
45, 2, 0.2%
46, 937, 100.0%
47, 169, 18.0%
48, 286, 30.5%
49, 2, 0.2%

行数の 1% 未満の一意の値を持つ変数のみを要約するように例を更新できます。

# summarize the percentage of unique values for each column using numpy
from urllib.request import urlopen
from numpy import loadtxt
from numpy import unique
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
data = loadtxt(urlopen(path), delimiter=',')
# summarize the number of unique values in each column
for i in range(data.shape[1]):
	num = len(unique(data[:, i]))
	percentage = float(num) / data.shape[0] * 100
	if percentage < 1:
		print('%d, %d, %.1f%%' % (i, num, percentage))

この例を実行すると、50 個の変数のうち 11 個に、行数の 1% 未満の一意の値を持つ数値変数があることがわかります。

これは、これらの行と列を削除する必要があるという意味ではありませんが、さらなる注意が必要です。

例えば:

  • おそらく、一意の値を順序値としてエンコードできるでしょうか?
  • おそらく、一意の値をカテゴリ値としてエンコードできるでしょうか?
  • モデルのスキルとデータセットから削除された各変数を比較してみてはいかがでしょうか?
21, 9, 1.0%
22, 1, 0.1%
24, 9, 1.0%
25, 8, 0.9%
26, 9, 1.0%
32, 4, 0.4%
36, 3, 0.3%
38, 9, 1.0%
39, 9, 1.0%
45, 2, 0.2%
49, 2, 0.2%

たとえば、行の 1% 未満の一意の値を持つ 11 列をすべて削除したいとします。以下の例はこれを示しています。

# delete columns where number of unique values is less than 1% of the rows
from pandas import read_csv
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
df = read_csv(path, header=None)
print(df.shape)
# get number of unique values for each column
counts = df.nunique()
# record columns to delete
to_del = [i for i,v in enumerate(counts) if (float(v)/df.shape[0]*100) < 1]
print(to_del)
# drop useless columns
df.drop(to_del, axis=1, inplace=True)
print(df.shape)

この例を実行すると、まずデータセットがロードされ、行と列の数がレポートされます。

各列の一意の値の数が計算され、一意の値の数が行の 1% 未満である列が特定されます。この場合は 11 列です。

次に、識別された列が DataFrame から削除され、DataFrame 内の行と列の数がレポートされて変更が確認されます。

(937, 50)
[21, 22, 24, 25, 26, 32, 36, 38, 39, 45, 49]
(937, 39)

分散が低い列を削除する

一意の値がほとんどない列を削除する問題に対する別のアプローチは、列の分散を考慮することです。

分散は、サンプルの値と平均値の二乗差の平均として変数に対して計算される統計量であることを思い出してください。

分散は、データセットから削除する列を識別するためのフィルターとして使用できます。単一の値を持つ列の分散は 0.0 であり、一意の値がほとんどない列の分散値は小さくなります。

scikit-learn ライブラリの VarianceThreshold クラスは、これを特徴選択のタイプとしてサポートします。 「しきい値」引数を指定してクラスのインスタンスを作成できます。単一の値を持つ列を削除する場合、デフォルトは 0.0 です。

次に、fit_transform() 関数を呼び出してデータセットに適合させて適用し、しきい値よりも低い分散を持つ列が自動的に削除されたデータセットの変換バージョンを作成します。

...
# define the transform
transform = VarianceThreshold()
# transform the input data
X_sel = transform.fit_transform(X)

これは、次のように石油流出データセットで実証できます。

# example of apply the variance threshold
from pandas import read_csv
from sklearn.feature_selection import VarianceThreshold
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
df = read_csv(path, header=None)
# split data into inputs and outputs
data = df.values
X = data[:, :-1]
y = data[:, -1]
print(X.shape, y.shape)
# define the transform
transform = VarianceThreshold()
# transform the input data
X_sel = transform.fit_transform(X)
print(X_sel.shape)

この例を実行すると、最初にデータセットがロードされ、次に変換が適用されて、分散が 0.0 のすべての列が削除されます。

データセットの形状は変換の前後でレポートされ、すべての値が同じである単一の列が削除されていることがわかります。

(937, 49) (937,)
(937, 48)

この例を拡張して、さまざまなしきい値を使用したときに何が起こるかを確認できます。

0.05 のステップ サイズで 0.0 から 0.5 までの一連のしきい値を定義できます。 0.0、0.05、0.1など

...
# define thresholds to check
thresholds = arange(0.0, 0.55, 0.05)

その後、指定されたしきい値ごとに、変換されたデータセット内の特徴の数をレポートできます。

...
# apply transform with each threshold
results = list()
for t in thresholds:
	# define the transform
	transform = VarianceThreshold(threshold=t)
	# transform the input data
	X_sel = transform.fit_transform(X)
	# determine the number of input features
	n_features = X_sel.shape[1]
	print('>Threshold=%.2f, Features=%d' % (t, n_features))
	# store the result
	results.append(n_features)

最後に、結果をプロットします。

これを組み合わせて、分散しきい値と選択された特徴の数を比較する完全な例を以下に示します。

# explore the effect of the variance thresholds on the number of selected features
from numpy import arange
from pandas import read_csv
from sklearn.feature_selection import VarianceThreshold
from matplotlib import pyplot
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/oil-spill.csv'
# load the dataset
df = read_csv(path, header=None)
# split data into inputs and outputs
data = df.values
X = data[:, :-1]
y = data[:, -1]
print(X.shape, y.shape)
# define thresholds to check
thresholds = arange(0.0, 0.55, 0.05)
# apply transform with each threshold
results = list()
for t in thresholds:
	# define the transform
	transform = VarianceThreshold(threshold=t)
	# transform the input data
	X_sel = transform.fit_transform(X)
	# determine the number of input features
	n_features = X_sel.shape[1]
	print('>Threshold=%.2f, Features=%d' % (t, n_features))
	# store the result
	results.append(n_features)
# plot the threshold vs the number of selected features
pyplot.plot(thresholds, results)
pyplot.show()

この例を実行すると、まずデータがロードされ、生のデータセットに 49 列があることが確認されます。

次に、VarianceThreshold が 0.0 ~ 0.5 の値で生データセットに適用され、変換適用後の残りの特徴の数がレポートされます。

データセット内の特徴の数が、変更されていないデータの 49 から、しきい値 0.15 の 35 まで急速に減少していることがわかります。その後、しきい値 0.5 で 31 (18 列が削除) に減少します。

(937, 49) (937,)
>Threshold=0.00, Features=48
>Threshold=0.05, Features=37
>Threshold=0.10, Features=36
>Threshold=0.15, Features=35
>Threshold=0.20, Features=35
>Threshold=0.25, Features=35
>Threshold=0.30, Features=35
>Threshold=0.35, Features=35
>Threshold=0.40, Features=35
>Threshold=0.45, Features=33
>Threshold=0.50, Features=31

次に、しきい値と変換されたデータセット内のフィーチャの数の関係を示す折れ線プロットが作成されます。

0.15 ~ 0.4 という小さいしきい値を使用した場合でも、多数の特徴 (14) がすぐに削除されることがわかります。

重複データを含む行を特定する

同一のデータを持つ行は、モデルの評価中に危険なほど誤解を招くものではないにしても、おそらく役に立ちません。

ここで、重複行とは、その行の各列の各値が別の行でまったく同じ順序 (同じ列値) で表示される行です。

…重複エントリが含まれる可能性のある生データを使用した場合、重複データを削除することは、データを正確に使用できるようにするための重要な手順になります。

— 173 ページ、Python によるデータ ラングリング、2016 年。

確率論的な観点から見ると、重複データはクラス ラベルまたはデータ分布の事前確率を調整するものと考えることができます。これは、事前確率に意図的にバイアスをかけたい場合に、単純ベイズのようなアルゴリズムに役立つ可能性があります。通常、これは当てはまらず、重複データを含む行を特定して削除することで、機械学習アルゴリズムのパフォーマンスが向上します。

アルゴリズム評価の観点から見ると、行が重複するとパフォーマンスが誤解を招く結果になります。たとえば、トレーニング/テスト分割または k 分割交差検証を使用している場合、トレーニング データセットとテスト データセットの両方に重複する行が表示される可能性があり、これらの行のモデルの評価は (またはそうあるべきです)正しい。これにより、目に見えないデータに対するパフォーマンスの推定が楽観的に偏ることになります。

データ重複排除は、重複検出、レコード リンケージ、レコード マッチング、エンティティ解決とも呼ばれ、同じ現実世界のエンティティを参照する 1 つ以上のリレーション内のタプルを識別するプロセスを指します。

— 47 ページ、データ クリーニング、2019 年。

これがデータセットまたは選択したモデルに当てはまらないと思われる場合は、それをテストするための対照実験を設計します。これは、生のデータセットと重複を削除したデータセットを使用してモデルのスキルを評価し、パフォーマンスを比較することで実現できます。別の実験には、ランダムに選択された異なる数の重複サンプルを使用してデータセットを増強することが含まれる場合があります。

pandas 関数 duplicad() は、指定された行が重複しているかどうかを報告します。すべての行は、重複ではないことを示す False または重複であることを示す True としてマークされます。重複がある場合は、予想どおり、最初に出現した行が False (デフォルト) としてマークされます。

以下の例では重複をチェックします。

# locate rows of duplicate data
from pandas import read_csv
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv'
# load the dataset
df = read_csv(path, header=None)
# calculate duplicates
dups = df.duplicated()
# report if there are any duplicates
print(dups.any())
# list all duplicate rows
print(df[dups])

この例を実行すると、まずデータセットがロードされ、次に行の重複が計算されます。

まず、重複行の存在が報告されます。この場合、重複がある (True) ことがわかります。

その後、すべての重複行がレポートされます。この場合、識別された 3 つの重複行が印刷されていることがわかります。

True
       0    1    2    3               4
34   4.9  3.1  1.5  0.1     Iris-setosa
37   4.9  3.1  1.5  0.1     Iris-setosa
142  5.8  2.7  5.1  1.9  Iris-virginica

重複データを含む行を削除する

重複データの行は、おそらくモデリングの前にデータセットから削除する必要があります。

データセットに単に重複した行がある場合は、データの保存について心配する必要はありません。これはすでに完成したデータセットの一部であるため、クリーンアップされたデータからこれらの行を削除またはドロップするだけで済みます。

— 186 ページ、Python によるデータ ラングリング、2016 年。

これを実現するには多くの方法がありますが、Pandas はまさにこれを実現する Drop_duplicates() 関数を提供します。

以下の例は、データセットから重複行を削除する方法を示しています。

# delete rows of duplicate data from the dataset
from pandas import read_csv
# define the location of the dataset
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv'
# load the dataset
df = read_csv(path, header=None)
print(df.shape)
# delete duplicate rows
df.drop_duplicates(inplace=True)
print(df.shape)

この例を実行すると、まずデータセットがロードされ、行と列の数がレポートされます。

次に、重複したデータの行が特定され、DataFrame から削除されます。次に、DataFrame の形状がレポートされ、変更が確認されます。

(150, 5)
(147, 5)

さらに読む

さらに詳しく知りたい場合は、このセクションでこのトピックに関するさらなるリソースを提供します。

チュートリアル

  • Python で機械学習データをロードする方法
  • データ クリーニング: 乱雑なデータを整理されたデータに変える

  • データ クリーニング、2019 年。
  • Python によるデータ ラングリング、2016 年。
  • 特徴エンジニアリングと選択、2019 年。

API

  • numpy.unique API。
  • pandas.DataFrame.nunique API。
  • sklearn.feature_selection.VarianceThreshold API。
  • pandas.DataFrame.drop API。
  • pandas.DataFrame.duplicated API。
  • pandas.DataFrame.drop_duplicates API。

まとめ

このチュートリアルでは、データセットに対して常に実行する必要がある基本的なデータ クリーニングについて説明しました。

具体的には、次のことを学びました。

  • 値が 1 つだけある列変数を特定して削除する方法。
  • 一意の値がほとんどない列変数を識別して考慮する方法。
  • 重複した観測値を含む行を特定して削除する方法。

ご質問はありますか?
以下のコメント欄にご質問ください。できる限りお答えいたします。

関連記事