LoginSignup
1

More than 3 years have passed since last update.

Data Every Day: 河川水中の溶存酸素予測

Posted at

tldr

KggleのDissolved oxygen prediction in river waterPredicting Oxygen in Rivers - Data Every Day #036に沿ってやっていきます。

実行環境はGoogle Colaboratorです。

インポート

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

import sklearn.preprocessing as sp
from sklearn.model_selection import train_test_split
import sklearn.linear_model as slm

import tensorflow as tf

データのダウンロード

Google Driveをマウントします。

from google.colab import drive
drive.mount('/content/drive')
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).

KaggleのAPIクライアントを初期化し、認証します。
認証情報はGoogle Drive内(/content/drive/My Drive/Colab Notebooks/Kaggle)にkaggle.jsonとして置いてあります。

import os
kaggle_path = "/content/drive/My Drive/Colab Notebooks/Kaggle"
os.environ['KAGGLE_CONFIG_DIR'] = kaggle_path

from kaggle.api.kaggle_api_extended import KaggleApi
api = KaggleApi()
api.authenticate() 

Kaggle APIを使ってデータをダウンロードします。

dataset_id = 'vbmokin/dissolved-oxygen-prediction-in-river-water'
dataset = api.dataset_list_files(dataset_id)
file_name = dataset.files[0].name
file_path = os.path.join(api.get_default_download_dir(), file_name)
file_path
Warning: Looks like you're using an outdated API Version, please consider updating (server 1.5.10 / client 1.5.9)





'/content/train.csv'
api.dataset_download_file(dataset_id, file_name, force=True, quiet=False)
100%|██████████| 17.6k/17.6k [00:00<00:00, 7.13MB/s]

Downloading train.csv to /content









True

データの読み込み

Padasを使ってダウンロードしてきたCSVファイルを読み込みます。

data = pd.read_csv(file_path)
data
Id target O2_1 O2_2 O2_3 O2_4 O2_5 O2_6 O2_7 NH4_1 NH4_2 NH4_3 NH4_4 NH4_5 NH4_6 NH4_7 NO2_1 NO2_2 NO2_3 NO2_4 NO2_5 NO2_6 NO2_7 NO3_1 NO3_2 NO3_3 NO3_4 NO3_5 NO3_6 NO3_7 BOD5_1 BOD5_2 BOD5_3 BOD5_4 BOD5_5 BOD5_6 BOD5_7
0 0 12.58 9.875 9.20 NaN NaN NaN NaN NaN 0.690 1.040 NaN NaN NaN NaN NaN 0.0940 0.0990 NaN NaN NaN NaN NaN 1.58 1.825 NaN NaN NaN NaN NaN 4.80 5.850 NaN NaN NaN NaN NaN
1 3 9.37 10.300 10.75 NaN NaN NaN NaN NaN 0.710 0.725 NaN NaN NaN NaN NaN 0.0585 0.0515 NaN NaN NaN NaN NaN 1.21 0.905 NaN NaN NaN NaN NaN 5.88 6.835 NaN NaN NaN NaN NaN
2 4 8.35 8.290 7.90 NaN NaN NaN NaN NaN 2.210 2.210 NaN NaN NaN NaN NaN 0.1000 0.1100 NaN NaN NaN NaN NaN 1.34 1.250 NaN NaN NaN NaN NaN 3.20 2.700 NaN NaN NaN NaN NaN
3 5 9.57 8.820 6.80 NaN NaN NaN NaN NaN 0.595 0.675 NaN NaN NaN NaN NaN 0.0460 0.0535 NaN NaN NaN NaN NaN 0.59 0.790 NaN NaN NaN NaN NaN 7.70 7.055 NaN NaN NaN NaN NaN
4 6 6.00 6.000 6.50 NaN NaN NaN NaN NaN 0.600 0.900 NaN NaN NaN NaN NaN 0.1800 0.3400 NaN NaN NaN NaN NaN 1.36 1.820 NaN NaN NaN NaN NaN 5.50 5.300 NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
142 208 6.80 7.700 7.50 NaN NaN NaN NaN NaN 0.380 1.900 NaN NaN NaN NaN NaN 0.6200 0.0640 NaN NaN NaN NaN NaN 2.80 3.330 NaN NaN NaN NaN NaN 5.00 5.800 NaN NaN NaN NaN NaN
143 211 5.30 6.300 5.65 NaN NaN NaN NaN NaN 0.370 0.500 NaN NaN NaN NaN NaN 0.6900 0.9500 NaN NaN NaN NaN NaN 4.37 3.160 NaN NaN NaN NaN NaN 8.00 8.000 NaN NaN NaN NaN NaN
144 212 8.60 8.600 11.00 NaN NaN NaN NaN NaN 2.400 3.600 NaN NaN NaN NaN NaN 0.1500 0.1400 NaN NaN NaN NaN NaN 0.53 3.000 NaN NaN NaN NaN NaN 6.80 7.200 NaN NaN NaN NaN NaN
145 213 9.90 9.600 14.10 NaN NaN NaN NaN NaN 0.310 0.500 NaN NaN NaN NaN NaN 0.2100 0.0800 NaN NaN NaN NaN NaN 3.10 3.500 NaN NaN NaN NaN NaN 5.20 7.800 NaN NaN NaN NaN NaN
146 214 6.50 6.500 7.70 NaN NaN NaN NaN NaN 0.190 0.260 NaN NaN NaN NaN NaN 0.1300 0.0720 NaN NaN NaN NaN NaN 0.00 0.000 NaN NaN NaN NaN NaN 3.40 4.100 NaN NaN NaN NaN NaN

147 rows × 37 columns

下準備

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 147 entries, 0 to 146
Data columns (total 37 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   Id      147 non-null    int64  
 1   target  147 non-null    float64
 2   O2_1    145 non-null    float64
 3   O2_2    145 non-null    float64
 4   O2_3    32 non-null     float64
 5   O2_4    31 non-null     float64
 6   O2_5    33 non-null     float64
 7   O2_6    37 non-null     float64
 8   O2_7    37 non-null     float64
 9   NH4_1   145 non-null    float64
 10  NH4_2   145 non-null    float64
 11  NH4_3   32 non-null     float64
 12  NH4_4   31 non-null     float64
 13  NH4_5   33 non-null     float64
 14  NH4_6   37 non-null     float64
 15  NH4_7   37 non-null     float64
 16  NO2_1   145 non-null    float64
 17  NO2_2   145 non-null    float64
 18  NO2_3   32 non-null     float64
 19  NO2_4   31 non-null     float64
 20  NO2_5   33 non-null     float64
 21  NO2_6   37 non-null     float64
 22  NO2_7   37 non-null     float64
 23  NO3_1   145 non-null    float64
 24  NO3_2   145 non-null    float64
 25  NO3_3   32 non-null     float64
 26  NO3_4   31 non-null     float64
 27  NO3_5   33 non-null     float64
 28  NO3_6   37 non-null     float64
 29  NO3_7   37 non-null     float64
 30  BOD5_1  145 non-null    float64
 31  BOD5_2  145 non-null    float64
 32  BOD5_3  32 non-null     float64
 33  BOD5_4  31 non-null     float64
 34  BOD5_5  33 non-null     float64
 35  BOD5_6  37 non-null     float64
 36  BOD5_7  37 non-null     float64
dtypes: float64(36), int64(1)
memory usage: 42.6 KB

欠損値の処理

data.isna().sum()
Id          0
target      0
O2_1        2
O2_2        2
O2_3      115
O2_4      116
O2_5      114
O2_6      110
O2_7      110
NH4_1       2
NH4_2       2
NH4_3     115
NH4_4     116
NH4_5     114
NH4_6     110
NH4_7     110
NO2_1       2
NO2_2       2
NO2_3     115
NO2_4     116
NO2_5     114
NO2_6     110
NO2_7     110
NO3_1       2
NO3_2       2
NO3_3     115
NO3_4     116
NO3_5     114
NO3_6     110
NO3_7     110
BOD5_1      2
BOD5_2      2
BOD5_3    115
BOD5_4    116
BOD5_5    114
BOD5_6    110
BOD5_7    110
dtype: int64

欠損値が100以上ある列は削除します。

null_columns = list(data.columns[data.isna().sum() > 100])
data = data.drop(null_columns, axis=1)
data
Id target O2_1 O2_2 NH4_1 NH4_2 NO2_1 NO2_2 NO3_1 NO3_2 BOD5_1 BOD5_2
0 0 12.58 9.875 9.20 0.690 1.040 0.0940 0.0990 1.58 1.825 4.80 5.850
1 3 9.37 10.300 10.75 0.710 0.725 0.0585 0.0515 1.21 0.905 5.88 6.835
2 4 8.35 8.290 7.90 2.210 2.210 0.1000 0.1100 1.34 1.250 3.20 2.700
3 5 9.57 8.820 6.80 0.595 0.675 0.0460 0.0535 0.59 0.790 7.70 7.055
4 6 6.00 6.000 6.50 0.600 0.900 0.1800 0.3400 1.36 1.820 5.50 5.300
... ... ... ... ... ... ... ... ... ... ... ... ...
142 208 6.80 7.700 7.50 0.380 1.900 0.6200 0.0640 2.80 3.330 5.00 5.800
143 211 5.30 6.300 5.65 0.370 0.500 0.6900 0.9500 4.37 3.160 8.00 8.000
144 212 8.60 8.600 11.00 2.400 3.600 0.1500 0.1400 0.53 3.000 6.80 7.200
145 213 9.90 9.600 14.10 0.310 0.500 0.2100 0.0800 3.10 3.500 5.20 7.800
146 214 6.50 6.500 7.70 0.190 0.260 0.1300 0.0720 0.00 0.000 3.40 4.100

147 rows × 12 columns

(data.isna().sum(axis=1) != 0).sum()
3

欠損値を含む行は3行だけなので、削除します。

data = data.dropna(axis=0)

不要な列の削除

data = data.drop('Id', axis=1)

X, Yデータの分割

y = data['target']
X = data.drop('target', axis=1)

スケーリング

scaler = sp.StandardScaler()
X = scaler.fit_transform(X)

トレーニング、テストデータの分割

X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7)

トレーニング

model = slm.LinearRegression()
model.fit(X_train, y_train)
model_R2 = model.score(X_test, y_test)
print('Model R^2 Score:', model_R2)
Model R^2 Score: -0.6563668417383994

次はyが高いか低いかの2値の予測をしてみます。

y
0      12.58
1       9.37
2       8.35
3       9.57
4       6.00
       ...  
142     6.80
143     5.30
144     8.60
145     9.90
146     6.50
Name: target, Length: 144, dtype: float64
y_new = pd.qcut(y, q=2, labels=[0,1])
X_train, X_test, y_train, y_test = train_test_split(X, y_new, train_size=0.7)
model = slm.LogisticRegression()
model.fit(X_train, y_train)
model_acc = model.score(X_test, y_test)
print('Model Accuracy:', model_acc)
Model Accuracy: 0.8181818181818182

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1