機械学習モデル作成シリーズ Step4 データ確認
機械学習モデル作成のStep4です。前回はロードしたデータを取り扱うデータ形式について扱いました。
今回はデータの確認を解説します。
4 Pandasによるデータ確認
通常、データをロードした後はデータを確認し、平均値や中央値などの統計情報から異常値の存在を確認します。目的はデータ概要の理解、異常値の除去や誤ったデータエントリの修正です。
データ例にはkaggle HSMコンペの脳波データを使用します。
データには有害な脳症状が発生した時の脳波についての情報が含まれており、id(識別子)やexpert_consensus(専門家の判断)、vote(その症状であると判断した専門家の数)等が含まれます。
今回はデータをロードし確認するための、pandasの各種メソッドを解説します。
4.0 データロード
csvデータをDataFrameとしてロードします。
train = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')
4.1 .shape
データの形状を確認します。二次元配列なら(x,y)三次元配列なら(a,b,c)のような形式で返されます。
・例
print(train.shape)
# 出力
# (106800, 15)
4.2 .groupby()
データを集約し、一意のデータ数を確認します。
・例
print(train.groupby("spectrogram_id").head(1).reset_index(drop=True).shape)
# 出力
# (11138, 15)
groupbyにより、一意の"spectrogram_id"列のデータに対して、他の行のデータが集約されます。
groupbyは集約データの操作とセットで利用され、今回は.head(1)なので、"sectrogram_id"ρテウのデータが重複していた場合、一番最初の行のみが保持されます。
またreset_indexにより、保持されたデータに新しく列インデックスが割り振られます。インデックスは行の参照や他のdfとの結合のキーとして利用できます。
・groupbyの例
import pandas as pd
# サンプルデータの作成
data = {'Category': ['A', 'A', 'B', 'B', 'C', 'C'],
'Values': [100, 150, 200, 250, 300, 350]}
df = pd.DataFrame(data)
print(df)
# 出力
# Category Values
# 0 A 100
# 1 A 150
# 2 B 200
# 3 B 250
# 4 C 300
# 5 C 350
# 各カテゴリーの最初のデータを取得
first_in_group = df.groupby('Category').head(1)
print(first_in_group)
# 出力
# Category Values
# 0 A 100
# 2 B 200
# 4 C 300
# 各カテゴリーのValuesの平均を計算。新しい列が生成されるため、インデックスが変更される(今回はCategory列がインデックスになっている)
mean_values = df.groupby('Category')['Values'].mean()
print(mean_values)
# 出力
# Category
# A 125.0
# B 225.0
# C 325.0
この操作はデータを集約します。
groupbyはできることが非常に多いので、また別の記事でも解説しようと思います。
4.3 .info()
データ各列の非欠損値の数と、データ型を確認します。
print(train.info())
# 出力
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 106800 entries, 0 to 106799
# Data columns (total 15 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 eeg_id 106800 non-null int64
# 1 eeg_sub_id 106800 non-null int64
# 2 eeg_label_offset_seconds 106800 non-null float64
# 3 spectrogram_id 106800 non-null int64
# 4 spectrogram_sub_id 106800 non-null int64
# 5 spectrogram_label_offset_seconds 106800 non-null float64
# 6 label_id 106800 non-null int64
# 7 patient_id 106800 non-null int64
# 8 expert_consensus 106800 non-null object
# 9 seizure_vote 106800 non-null int64
# 10 lpd_vote 106800 non-null int64
# 11 gpd_vote 106800 non-null int64
# 12 lrda_vote 106800 non-null int64
# 13 grda_vote 106800 non-null int64
# 14 other_vote 106800 non-null int64
# dtypes: float64(2), int64(12), object(1)
# memory usage: 12.2+ MB
# None # 戻り値
欠損値は見当たらず、expert_consensus列がobject型、その他の列がint型やfloat型であることが分かります。
object型は
・文字列(str)のデータ
・日付や時刻を含む列で、Pandasが特定の日付/時刻型として認識できない場合
・リスト、辞書などのPythonの複合データ型
・Pythonの任意のオブジェクト
などに割り当てられます。機械学習モデルは数値しか扱えないため、このデータは何かしらの処理をする必要があります。
4.4 .dtypes()
データ型を確認します。基本的にはinfo()と同じですが、dtypes()は結果をpd.Seriesで返すため、この結果をそのまま別の処理に使用することができます。
※info()の返り値はNoneです。
print(train.dtypes())
# 出力
# eeg_id int64
# eeg_sub_id int64
# eeg_label_offset_seconds float64
# spectrogram_id int64
# spectrogram_sub_id int64
# spectrogram_label_offset_seconds float64
# label_id int64
# patient_id int64
# expert_consensus object
# seizure_vote int64
# lpd_vote int64
# gpd_vote int64
# lrda_vote int64
# grda_vote int64
# other_vote int64
# dtype: object
4.5 .describe()
統計情報を確認します。数値型(intやfloat)の列に対してのみ適用されます。
返り値はDataFrameです。
※統計情報は欠損値を除外した上で計算されます。
・count 非欠損値の数
・maen 平均値。合計を要素数で割ったもの
・std 標準偏差。データが平均値からどの程度バラついているか
・min 最小値
・25% 第一四分位数(Q1)。データを大きさ順に並べた時に下から25%の位置にある値
・50% 中央値(Q2)。データを大きさ順に並べた時に50%の位置にある値
・75% 第三四分位数(Q3)。データを大きさ順に並べた時に下から75%の位置にある値
・max 最大値
print(train.describe())
# 出力
# eeg_id eeg_sub_id eeg_label_offset_seconds spectrogram_id spectrogram_sub_id spectrogram_label_offset_seconds label_id patient_id seizure_vote lpd_vote gpd_vote lrda_vote grda_vote other_vote
# count 1.068000e+05 106800.000000 106800.000000 1.068000e+05 106800.000000 106800.000000 1.068000e+05 106800.000000 106800.000000 106800.000000 106800.000000 106800.000000 106800.000000 106800.000000
# mean 2.104387e+09 26.286189 118.817228 1.067262e+09 43.733596 520.431404 2.141415e+09 32304.428493 0.878024 1.138783 1.264925 0.948296 1.059185 1.966283
# std 1.233371e+09 69.757658 314.557803 6.291475e+08 104.292116 1449.759868 1.241670e+09 18538.196252 1.538873 2.818845 3.131889 2.136799 2.228492 3.621180
# min 5.686570e+05 0.000000 0.000000 3.537330e+05 0.000000 0.000000 3.380000e+02 56.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
# 25% 1.026896e+09 1.000000 6.000000 5.238626e+08 2.000000 12.000000 1.067419e+09 16707.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
# 50% 2.071326e+09 5.000000 26.000000 1.057904e+09 8.000000 62.000000 2.138332e+09 32068.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
# 75% 3.172787e+09 16.000000 82.000000 1.623195e+09 29.000000 394.000000 3.217816e+09 48036.000000 1.000000 1.000000 0.000000 1.000000 1.000000 2.000000
# max 4.294958e+09 742.000000 3372.000000 2.147388e+09 1021.000000 17632.000000 4.294934e+09 65494.000000 19.000000 18.000000 16.000000 15.000000 15.000000 25.000000
4.5 .describe(include=['O'])
統計情報を確認します。object型の列に対してのみ適用されます。
※統計情報は欠損値を除外した上で計算されます。
※include='all'で数値型とobject型の両方に適用されます。
・count 非欠損値の数
・unique 列に存在する一意なデータの数
・top 列に最も多く出現する値
・freq topの値が出現する回数
print(train.describe(include=['O'])) # 大文字のo
# 出力
# expert_consensus
# count 106800
# unique 6
# top Seizure
# freq 20933
4.6 ['列名'].unique()
列に存在する一意のデータを確認します。
Numpyのndarrayを返します。
print(train['expert_consensus']).unique())
# 出力
# array(['Seizure', 'GPD', 'LRDA', 'Other', 'GRDA', 'LPD'], dtype=object)
4.7 ['列名'].nunique()
列に存在する一意のデータの数を確認します。unique()のデータ数です。
print(train['expert_consensus']).nunique())
# 出力
# 6
4.8 .isnull().sum()
欠損値を確認します。
isnull(): 欠損値の位置がTrueのdfを生成
sum(): 列ごとの数を集計
print(train.isnull().sum())
# 出力
# eeg_id 0
# eeg_sub_id 0
# eeg_label_offset_seconds 0
# spectrogram_id 0
# spectrogram_sub_id 0
# spectrogram_label_offset_seconds 0
# label_id 0
# patient_id 0
# expert_consensus 0
# seizure_vote 0
# lpd_vote 0
# gpd_vote 0
# lrda_vote 0
# grda_vote 0
# other_vote 0
# dtype: int64
すべての行に欠損値が含まれていないことが分かります。
DataFrameをsumで集計するのでSeriesを返します。
4.9 .isnull().sum().sum()
欠損値を確認します。
.isnull().sum()の合計なので、前データに含まれる欠損地の数を表します。
print(train.isnull().sum().sum())
# 出力
# 0
4.10 .value_counts()
列に含まれるデータの種類と数を確認します。
各データがいくつ含まれているのかをSeries/DataFarmeで返します
print(train['expert_consensus'].value_counts())
# 出力
# expert_consensus
# Seizure 20933
# GRDA 18861
# Other 18808
# GPD 16702
# LRDA 16640
# LPD 14856
# Name: count, dtype: int64
print(train['sizure_vote'].value_counts())
seizure_vote
# 出力
# 0 73906
# 3 19520
# 1 6475
# 2 2329
# 5 1825
# 4 1745
# 6 336
# 7 313
# 8 91
# 9 57
# 10 54
# 15 36
# 13 30
# 11 29
# 14 25
# 12 22
# 19 4
# 16 3
# Name: count, dtype: int64
コード全文
# kaggleのnotebook環境での実行を推奨
class preprocessing():
def __init__(self, train):
self.train = train
def grouping(self):
train = self.train.groupby("id").head(1).reset_index(drop=True)
print(train.shape)
def data_check(self):
print("\n" + "/"*10 + "shape" + "/"*20)
print(self.train.shape)
print("\n" + "/"*10 + "shape in unique id" + "/"*20)
self.grouping()
print("\n" + "/"*10 + "info()" + "/"*20)
display(self.train.info())
print("\n" + "/"*10 + "dtypes" + "/"*20)
display(self.train.dtypes)
print("\n" + "/"*10 + "descrive()" + "/"*20)
display(self.train.describe())
# descrive categorical data
print("\n" + "/"*10 + "descrive(include=[0])" + "/"*20)
display(self.train.describe(include=['O']))
print("\n" + "/"*10 + "unique() expert_consensus" + "/"*20)
display(self.train['expert_consensus'].unique())
print("\n" + "/"*10 + "nunique() expert_consensus" + "/"*20)
display(self.train['expert_consensus'].nunique())
print("\n" + "/"*10 + "unique() seizure_vote" + "/"*20)
display(self.train['seizure_vote'].unique())
print("\n" + "/"*10 + "nunique() seizure_vote" + "/"*20)
display(self.train['seizure_vote'].nunique())
# num of missing value in every column
print("\n" + "/"*10 + "isnull().sum()" + "/"*20)
display(self.train.isnull().sum())
# num of missing value whole data
print("\n" + "/"*10 + "isnull().sum().sum()" + "/"*20)
display(self.train.isnull().sum().sum())
# check appearance frequency of specify column
print("\n" + "/"*10 + "value_counts() expert_consensus" + "/"*20)
display(self.train['expert_consensus'].value_counts())
print("\n" + "/"*10 + "value_counts() seizure_vote" + "/"*20)
display(self.train['seizure_vote'].value_counts())
def load_data():
train = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')
prep = preprocessing(train)
prep.data_check()
load_data()
//////////shape////////////////////
(106800, 15)
tuple
//////////shape in unique spectrogram_id////////////////////
(11138, 15)
tuple
//////////info()////////////////////
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 106800 entries, 0 to 106799
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 eeg_id 106800 non-null int64
1 eeg_sub_id 106800 non-null int64
2 eeg_label_offset_seconds 106800 non-null float64
3 spectrogram_id 106800 non-null int64
4 spectrogram_sub_id 106800 non-null int64
5 spectrogram_label_offset_seconds 106800 non-null float64
6 label_id 106800 non-null int64
7 patient_id 106800 non-null int64
8 expert_consensus 106800 non-null object
9 seizure_vote 106800 non-null int64
10 lpd_vote 106800 non-null int64
11 gpd_vote 106800 non-null int64
12 lrda_vote 106800 non-null int64
13 grda_vote 106800 non-null int64
14 other_vote 106800 non-null int64
dtypes: float64(2), int64(12), object(1)
memory usage: 12.2+ MB
None
NoneType
//////////dtypes////////////////////
eeg_id int64
eeg_sub_id int64
eeg_label_offset_seconds float64
spectrogram_id int64
spectrogram_sub_id int64
spectrogram_label_offset_seconds float64
label_id int64
patient_id int64
expert_consensus object
seizure_vote int64
lpd_vote int64
gpd_vote int64
lrda_vote int64
grda_vote int64
other_vote int64
dtype: object
pandas.core.series.Series
//////////descrive()////////////////////
eeg_id eeg_sub_id eeg_label_offset_seconds spectrogram_id spectrogram_sub_id spectrogram_label_offset_seconds label_id patient_id seizure_vote lpd_vote gpd_vote lrda_vote grda_vote other_vote
count 1.068000e+05 106800.000000 106800.000000 1.068000e+05 106800.000000 106800.000000 1.068000e+05 106800.000000 106800.000000 106800.000000 106800.000000 106800.000000 106800.000000 106800.000000
mean 2.104387e+09 26.286189 118.817228 1.067262e+09 43.733596 520.431404 2.141415e+09 32304.428493 0.878024 1.138783 1.264925 0.948296 1.059185 1.966283
std 1.233371e+09 69.757658 314.557803 6.291475e+08 104.292116 1449.759868 1.241670e+09 18538.196252 1.538873 2.818845 3.131889 2.136799 2.228492 3.621180
min 5.686570e+05 0.000000 0.000000 3.537330e+05 0.000000 0.000000 3.380000e+02 56.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
25% 1.026896e+09 1.000000 6.000000 5.238626e+08 2.000000 12.000000 1.067419e+09 16707.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
50% 2.071326e+09 5.000000 26.000000 1.057904e+09 8.000000 62.000000 2.138332e+09 32068.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
75% 3.172787e+09 16.000000 82.000000 1.623195e+09 29.000000 394.000000 3.217816e+09 48036.000000 1.000000 1.000000 0.000000 1.000000 1.000000 2.000000
max 4.294958e+09 742.000000 3372.000000 2.147388e+09 1021.000000 17632.000000 4.294934e+09 65494.000000 19.000000 18.000000 16.000000 15.000000 15.000000 25.000000
pandas.core.frame.DataFrame
//////////descrive(include=[0])////////////////////
expert_consensus
count 106800
unique 6
top Seizure
freq 20933
pandas.core.frame.DataFrame
//////////unique() expert_consensus////////////////////
array(['Seizure', 'GPD', 'LRDA', 'Other', 'GRDA', 'LPD'], dtype=object)
numpy.ndarray
//////////nunique() expert_consensus////////////////////
6
int
//////////unique() seizure_vote////////////////////
array([ 3, 0, 1, 4, 5, 6, 13, 2, 12, 14, 7, 10, 15, 9, 8, 11, 16,
19])
numpy.ndarray
//////////nunique() seizure_vote////////////////////
18
int
//////////isnull().sum()////////////////////
eeg_id 0
eeg_sub_id 0
eeg_label_offset_seconds 0
spectrogram_id 0
spectrogram_sub_id 0
spectrogram_label_offset_seconds 0
label_id 0
patient_id 0
expert_consensus 0
seizure_vote 0
lpd_vote 0
gpd_vote 0
lrda_vote 0
grda_vote 0
other_vote 0
dtype: int64
pandas.core.series.Series
//////////isnull().sum().sum()////////////////////
0
numpy.int64
//////////value_counts() expert_consensus////////////////////
expert_consensus
Seizure 20933
GRDA 18861
Other 18808
GPD 16702
LRDA 16640
LPD 14856
Name: count, dtype: int64
pandas.core.series.Series
//////////value_counts() seizure_vote////////////////////
seizure_vote
0 73906
3 19520
1 6475
2 2329
5 1825
4 1745
6 336
7 313
8 91
9 57
10 54
15 36
13 30
11 29
14 25
12 22
19 4
16 3
Name: count, dtype: int64
pandas.core.series.Series
Step4まとめ
今回は、ロードしたデータを確認する方法を紹介しました。
Step5はデータの前処理について解説する予定です。
読んでいただきありがとうございました。
Discussion