Pandas 入門¶
Pandas はデータ操作によく用いられるパッケージであり、CSV などの一般的なデータ形式で保存されたデータの読み込みや、条件を指定しての一部データの抽出など、機械学習手法で取り扱うデータを整理するのに便利です。
今回は Pandas の以下の代表的な機能の使い方を説明します。
CSV ファイルの読み書き
統計量の算出
並べ替え
データの選択
条件指定による選択
欠損値の除去 / 補間
ndarray とデータフレームを相互に変換
グラフの描画
まず Pandas パッケージを読み込みましょう。 pandas
は pd
という別名を与えて用いるのが一般的です。
[1]:
import pandas as pd
CSV ファイルの読み書き¶
データセットは Google Colaboratory で用意されているサンプルデータを使用します。 Google Colaboratory 以外で実行する場合は、こちらをダウンロードして、使用してください。
Pandas では CSV ファイルを読み込むための pd.read_csv()
という関数が用意されています。 こちらを使って CSV ファイルを読み込みます。
[2]:
# データセットの読み込み
df = pd.read_csv('sample_data/california_housing_train.csv')
df
という変数名は、データフレーム (data frame) という Pandas で中心的に用いられるデータ構造 (data structure) を表すクラスの名前の頭文字に由来しています。 pd.read_csv()
関数は、CSV ファイルの内容を DataFrame
オブジェクトに読み込みます。
[3]:
# 型の確認
type(df)
[3]:
pandas.core.frame.DataFrame
DataFrame の表示¶
df
に読み込まれたデータの中身の確認してみましょう。 Jupyter Notebook 上では、大きな DataFrame を表示しようとすると自動的に一部が省略されることがあります。
[4]:
df
[4]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 |
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 |
4 | -114.57 | 33.57 | 20.0 | 1454.0 | 326.0 | 624.0 | 262.0 | 1.9250 | 65500.0 |
5 | -114.58 | 33.63 | 29.0 | 1387.0 | 236.0 | 671.0 | 239.0 | 3.3438 | 74000.0 |
6 | -114.58 | 33.61 | 25.0 | 2907.0 | 680.0 | 1841.0 | 633.0 | 2.6768 | 82400.0 |
7 | -114.59 | 34.83 | 41.0 | 812.0 | 168.0 | 375.0 | 158.0 | 1.7083 | 48500.0 |
8 | -114.59 | 33.61 | 34.0 | 4789.0 | 1175.0 | 3134.0 | 1056.0 | 2.1782 | 58400.0 |
9 | -114.60 | 34.83 | 46.0 | 1497.0 | 309.0 | 787.0 | 271.0 | 2.1908 | 48100.0 |
10 | -114.60 | 33.62 | 16.0 | 3741.0 | 801.0 | 2434.0 | 824.0 | 2.6797 | 86500.0 |
11 | -114.60 | 33.60 | 21.0 | 1988.0 | 483.0 | 1182.0 | 437.0 | 1.6250 | 62000.0 |
12 | -114.61 | 34.84 | 48.0 | 1291.0 | 248.0 | 580.0 | 211.0 | 2.1571 | 48600.0 |
13 | -114.61 | 34.83 | 31.0 | 2478.0 | 464.0 | 1346.0 | 479.0 | 3.2120 | 70400.0 |
14 | -114.63 | 32.76 | 15.0 | 1448.0 | 378.0 | 949.0 | 300.0 | 0.8585 | 45000.0 |
15 | -114.65 | 34.89 | 17.0 | 2556.0 | 587.0 | 1005.0 | 401.0 | 1.6991 | 69100.0 |
16 | -114.65 | 33.60 | 28.0 | 1678.0 | 322.0 | 666.0 | 256.0 | 2.9653 | 94900.0 |
17 | -114.65 | 32.79 | 21.0 | 44.0 | 33.0 | 64.0 | 27.0 | 0.8571 | 25000.0 |
18 | -114.66 | 32.74 | 17.0 | 1388.0 | 386.0 | 775.0 | 320.0 | 1.2049 | 44000.0 |
19 | -114.67 | 33.92 | 17.0 | 97.0 | 24.0 | 29.0 | 15.0 | 1.2656 | 27500.0 |
20 | -114.68 | 33.49 | 20.0 | 1491.0 | 360.0 | 1135.0 | 303.0 | 1.6395 | 44400.0 |
21 | -114.73 | 33.43 | 24.0 | 796.0 | 243.0 | 227.0 | 139.0 | 0.8964 | 59200.0 |
22 | -114.94 | 34.55 | 20.0 | 350.0 | 95.0 | 119.0 | 58.0 | 1.6250 | 50000.0 |
23 | -114.98 | 33.82 | 15.0 | 644.0 | 129.0 | 137.0 | 52.0 | 3.2097 | 71300.0 |
24 | -115.22 | 33.54 | 18.0 | 1706.0 | 397.0 | 3424.0 | 283.0 | 1.6250 | 53500.0 |
25 | -115.32 | 32.82 | 34.0 | 591.0 | 139.0 | 327.0 | 89.0 | 3.6528 | 100000.0 |
26 | -115.37 | 32.82 | 30.0 | 1602.0 | 322.0 | 1130.0 | 335.0 | 3.5735 | 71100.0 |
27 | -115.37 | 32.82 | 14.0 | 1276.0 | 270.0 | 867.0 | 261.0 | 1.9375 | 80900.0 |
28 | -115.37 | 32.81 | 32.0 | 741.0 | 191.0 | 623.0 | 169.0 | 1.7604 | 68600.0 |
29 | -115.37 | 32.81 | 23.0 | 1458.0 | 294.0 | 866.0 | 275.0 | 2.3594 | 74300.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
16970 | -124.17 | 40.80 | 52.0 | 1606.0 | 419.0 | 891.0 | 367.0 | 1.5850 | 75500.0 |
16971 | -124.17 | 40.80 | 52.0 | 1557.0 | 344.0 | 758.0 | 319.0 | 1.8529 | 62500.0 |
16972 | -124.17 | 40.79 | 43.0 | 2285.0 | 479.0 | 1169.0 | 482.0 | 1.9688 | 70500.0 |
16973 | -124.17 | 40.78 | 39.0 | 1606.0 | 330.0 | 731.0 | 327.0 | 1.6369 | 68300.0 |
16974 | -124.17 | 40.77 | 30.0 | 1895.0 | 366.0 | 990.0 | 359.0 | 2.2227 | 81300.0 |
16975 | -124.17 | 40.76 | 26.0 | 1776.0 | 361.0 | 992.0 | 380.0 | 2.8056 | 82800.0 |
16976 | -124.17 | 40.75 | 13.0 | 2171.0 | 339.0 | 951.0 | 353.0 | 4.8516 | 116100.0 |
16977 | -124.17 | 40.62 | 32.0 | 1595.0 | 309.0 | 706.0 | 277.0 | 2.8958 | 86400.0 |
16978 | -124.18 | 40.79 | 39.0 | 1836.0 | 352.0 | 883.0 | 337.0 | 1.7450 | 70500.0 |
16979 | -124.18 | 40.78 | 37.0 | 1453.0 | 293.0 | 867.0 | 310.0 | 2.5536 | 70200.0 |
16980 | -124.18 | 40.78 | 34.0 | 1592.0 | 364.0 | 950.0 | 317.0 | 2.1607 | 67000.0 |
16981 | -124.18 | 40.78 | 33.0 | 1076.0 | 222.0 | 656.0 | 236.0 | 2.5096 | 72200.0 |
16982 | -124.18 | 40.62 | 35.0 | 952.0 | 178.0 | 480.0 | 179.0 | 3.0536 | 107000.0 |
16983 | -124.19 | 41.78 | 15.0 | 3140.0 | 714.0 | 1645.0 | 640.0 | 1.6654 | 74600.0 |
16984 | -124.19 | 40.78 | 37.0 | 1371.0 | 319.0 | 640.0 | 260.0 | 1.8242 | 70000.0 |
16985 | -124.19 | 40.77 | 30.0 | 2975.0 | 634.0 | 1367.0 | 583.0 | 2.4420 | 69000.0 |
16986 | -124.19 | 40.73 | 21.0 | 5694.0 | 1056.0 | 2907.0 | 972.0 | 3.5363 | 90100.0 |
16987 | -124.21 | 41.77 | 17.0 | 3461.0 | 722.0 | 1947.0 | 647.0 | 2.5795 | 68400.0 |
16988 | -124.21 | 41.75 | 20.0 | 3810.0 | 787.0 | 1993.0 | 721.0 | 2.0074 | 66900.0 |
16989 | -124.21 | 40.75 | 32.0 | 1218.0 | 331.0 | 620.0 | 268.0 | 1.6528 | 58100.0 |
16990 | -124.22 | 41.73 | 28.0 | 3003.0 | 699.0 | 1530.0 | 653.0 | 1.7038 | 78300.0 |
16991 | -124.23 | 41.75 | 11.0 | 3159.0 | 616.0 | 1343.0 | 479.0 | 2.4805 | 73200.0 |
16992 | -124.23 | 40.81 | 52.0 | 1112.0 | 209.0 | 544.0 | 172.0 | 3.3462 | 50800.0 |
16993 | -124.23 | 40.54 | 52.0 | 2694.0 | 453.0 | 1152.0 | 435.0 | 3.0806 | 106700.0 |
16994 | -124.25 | 40.28 | 32.0 | 1430.0 | 419.0 | 434.0 | 187.0 | 1.9417 | 76100.0 |
16995 | -124.26 | 40.58 | 52.0 | 2217.0 | 394.0 | 907.0 | 369.0 | 2.3571 | 111400.0 |
16996 | -124.27 | 40.69 | 36.0 | 2349.0 | 528.0 | 1194.0 | 465.0 | 2.5179 | 79000.0 |
16997 | -124.30 | 41.84 | 17.0 | 2677.0 | 531.0 | 1244.0 | 456.0 | 3.0313 | 103600.0 |
16998 | -124.30 | 41.80 | 19.0 | 2672.0 | 552.0 | 1298.0 | 478.0 | 1.9797 | 85800.0 |
16999 | -124.35 | 40.54 | 52.0 | 1820.0 | 300.0 | 806.0 | 270.0 | 3.0147 | 94600.0 |
17000 rows × 9 columns
先頭の数件だけを表示¶
データを数件のみ確認したい場合は、データフレームがもつ df.head()
メソッドを使用します。 df.head()
はデフォルトで先頭から 5 件のデータを表示しますが、df.head(3)
のように引数に表示したいデータ件数を指定すると、指定された件数だけを表示することもできます。 それでは、df.head()
を実行してみましょう。
[5]:
df.head()
[5]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 |
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 |
4 | -114.57 | 33.57 | 20.0 | 1454.0 | 326.0 | 624.0 | 262.0 | 1.9250 | 65500.0 |
[6]:
df.head(3)
[6]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 |
特定の列を抽出したい場合は、df
に対し、Python の辞書オブジェクトに行うように []
を使って取り出したい列の名前を指定します。
[7]:
df['longitude'].head(3)
[7]:
0 -114.31
1 -114.47
2 -114.56
Name: longitude, dtype: float64
CSV ファイルの保存¶
Pandas ではデータフレームオブジェクトの内容を CSV ファイルとして保存するための df.to_csv()
というメソッドが用意されています。
[8]:
df.to_csv('sample.csv')
[9]:
!ls sample.csv
sample.csv
統計量の算出¶
データフレームには、中のデータに対し統計量を計算するためのメソッドも用意されています。 代表的なものを紹介します。
[11]:
# 平均
df.mean()
[11]:
longitude -119.562108
latitude 35.625225
housing_median_age 28.589353
total_rooms 2643.664412
total_bedrooms 539.410824
population 1429.573941
households 501.221941
median_income 3.883578
median_house_value 207300.912353
dtype: float64
[12]:
# 分散
df.var()
[12]:
longitude 4.020692e+00
latitude 4.568221e+00
housing_median_age 1.584310e+02
total_rooms 4.752169e+06
total_bedrooms 1.776618e+05
population 1.317566e+06
households 1.478563e+05
median_income 3.641061e+00
median_house_value 1.345223e+10
dtype: float64
[13]:
# 各列の None, NaN, NaT のいずれでもない値の数
df.count()
[13]:
longitude 17000
latitude 17000
housing_median_age 17000
total_rooms 17000
total_bedrooms 17000
population 17000
households 17000
median_income 17000
median_house_value 17000
dtype: int64
ここで、データの特徴をおおまかに調べるために便利な df.describe()
メソッドを実行してみましょう。
[14]:
# データの概要
df.describe()
[14]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
count | 17000.000000 | 17000.000000 | 17000.000000 | 17000.000000 | 17000.000000 | 17000.000000 | 17000.000000 | 17000.000000 | 17000.000000 |
mean | -119.562108 | 35.625225 | 28.589353 | 2643.664412 | 539.410824 | 1429.573941 | 501.221941 | 3.883578 | 207300.912353 |
std | 2.005166 | 2.137340 | 12.586937 | 2179.947071 | 421.499452 | 1147.852959 | 384.520841 | 1.908157 | 115983.764387 |
min | -124.350000 | 32.540000 | 1.000000 | 2.000000 | 1.000000 | 3.000000 | 1.000000 | 0.499900 | 14999.000000 |
25% | -121.790000 | 33.930000 | 18.000000 | 1462.000000 | 297.000000 | 790.000000 | 282.000000 | 2.566375 | 119400.000000 |
50% | -118.490000 | 34.250000 | 29.000000 | 2127.000000 | 434.000000 | 1167.000000 | 409.000000 | 3.544600 | 180400.000000 |
75% | -118.000000 | 37.720000 | 37.000000 | 3151.250000 | 648.250000 | 1721.000000 | 605.250000 | 4.767000 | 265000.000000 |
max | -114.310000 | 41.950000 | 52.000000 | 37937.000000 | 6445.000000 | 35682.000000 | 6082.000000 | 15.000100 | 500001.000000 |
また、もうひとつ便利なメソッドに相関係数を算出する df.corr()
があります。 入力変数間や入出力間の相関係数を確認することができます。
[15]:
# 相関係数の算出
df.corr()
[15]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
longitude | 1.000000 | -0.925208 | -0.114250 | 0.047010 | 0.071802 | 0.101674 | 0.059628 | -0.015485 | -0.044982 |
latitude | -0.925208 | 1.000000 | 0.016454 | -0.038773 | -0.069373 | -0.111261 | -0.074902 | -0.080303 | -0.144917 |
housing_median_age | -0.114250 | 0.016454 | 1.000000 | -0.360984 | -0.320434 | -0.295890 | -0.302754 | -0.115932 | 0.106758 |
total_rooms | 0.047010 | -0.038773 | -0.360984 | 1.000000 | 0.928403 | 0.860170 | 0.919018 | 0.195383 | 0.130991 |
total_bedrooms | 0.071802 | -0.069373 | -0.320434 | 0.928403 | 1.000000 | 0.881169 | 0.980920 | -0.013495 | 0.045783 |
population | 0.101674 | -0.111261 | -0.295890 | 0.860170 | 0.881169 | 1.000000 | 0.909247 | -0.000638 | -0.027850 |
households | 0.059628 | -0.074902 | -0.302754 | 0.919018 | 0.980920 | 0.909247 | 1.000000 | 0.007644 | 0.061031 |
median_income | -0.015485 | -0.080303 | -0.115932 | 0.195383 | -0.013495 | -0.000638 | 0.007644 | 1.000000 | 0.691871 |
median_house_value | -0.044982 | -0.144917 | 0.106758 | 0.130991 | 0.045783 | -0.027850 | 0.061031 | 0.691871 | 1.000000 |
並べ替え¶
データフレームのある列を抽出し、df.sort_values()
メソッドを呼び出すことで値の並べ替え (sort) を行うことができます。 なお、このメソッドは並べ替えが終わったあとの値でもとのデータフレーム内の値を置き換えることまでは行わず、結果を返します。 そこで、別の変数で結果を受け取り、始めの 5 行を表示することで並べ替えが行われたことを確認してみましょう。
df.sort_values()
は、デフォルトでは昇順 (ascending) に並べ替えを行います。昇順とは、だんだん値が大きくなっていくように並べ替えるときの並べ方のことで、逆にだんだん値が小さくなっていくように並べ替えるときは、降順 (descending) に並べると言います。
df.sort_values()
は並べ替えを行いたい列の名前を by
という引数で受け取ります。また、デフォルトでは昇順に並べ替えを行います。
[16]:
# total_rooms 列の値を昇順に並べ替え
df_as = df.sort_values(by='total_rooms')
[17]:
df_as.head()
[17]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
2990 | -117.79 | 35.21 | 4.0 | 2.0 | 2.0 | 6.0 | 2.0 | 2.3750 | 137500.0 |
16309 | -122.50 | 37.79 | 52.0 | 8.0 | 1.0 | 13.0 | 1.0 | 15.0001 | 500001.0 |
8188 | -118.44 | 34.28 | 46.0 | 11.0 | 11.0 | 24.0 | 13.0 | 2.8750 | 162500.0 |
15369 | -122.29 | 37.81 | 46.0 | 12.0 | 4.0 | 18.0 | 7.0 | 0.4999 | 67500.0 |
15656 | -122.37 | 37.60 | 26.0 | 15.0 | 3.0 | 11.0 | 3.0 | 5.0480 | 350000.0 |
降順に並べ替える場合は、ascending=False
という引数の指定を行います。
[18]:
# total_rooms の列の値を降順に並べ替え
df_de = df.sort_values(by='total_rooms', ascending=False)
[19]:
df_de.head()
[19]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
2871 | -117.74 | 33.89 | 4.0 | 37937.0 | 5471.0 | 16122.0 | 5189.0 | 7.4947 | 366300.0 |
12772 | -121.79 | 36.64 | 11.0 | 32627.0 | 6445.0 | 28566.0 | 6082.0 | 2.3087 | 118800.0 |
2969 | -117.78 | 34.03 | 8.0 | 32054.0 | 5290.0 | 15507.0 | 5050.0 | 6.0191 | 253900.0 |
8881 | -118.78 | 34.16 | 9.0 | 30405.0 | 4093.0 | 12873.0 | 3931.0 | 8.0137 | 399200.0 |
1116 | -117.12 | 33.52 | 4.0 | 30401.0 | 4957.0 | 13251.0 | 4339.0 | 4.5841 | 212300.0 |
データの選択¶
着目したい要素や、行、列を選択する方法を紹介します。 scikit-learn 入門の章で行ったように、入力値 x
と目標値 t
が別の列として同じ配列に格納されている場合は、指定した列だけを取り出す操作を行って、結果を別の変数に代入する操作を行います。 このように、特定の列の選択や列を範囲指定して選択する機能が Pandas のデータフレームにも用意されています。
今回は最後の列 median_house_value
と、それ以外の列をそれぞれ取り出して、別々の変数に格納してみましょう。
列や行の選択を行う方法は複数あります。 ここでは、整数インデックスを用いてデータの部分選択を行う df.iloc[]
を紹介します。
[20]:
# データの確認
df.head(3)
[20]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 |
[21]:
# df.iloc[行, 列]
# 0 行目 longitude 列の選択
df.iloc[0, 0]
[21]:
-114.31
[22]:
# 1 行目 latitude 列の選択
df.iloc[1, 1]
[22]:
34.4
iloc
には NumPy の ndarray の中の値を部分的に選択するのと同様のスライス表記を用いることができます。 負のインデックスを使い、末尾の要素からの個数を用いて位置指定を行うこともできます。
[23]:
# すべての行の、最後の列を選択
t = df.iloc[:, -1]
[24]:
# 先頭3件の表示
t.head(3)
[24]:
0 66900.0
1 80100.0
2 85700.0
Name: median_house_value, dtype: float64
[25]:
# 型の確認
type(t)
[25]:
pandas.core.series.Series
1 行だけ、もしくは 1 列だけ抽出した場合は、シリーズ (series) オブジェクトが返されます。
[26]:
# すべての行の、先頭の列から末尾の列のひとつ手前までを選択
x = df.iloc[:, 0:-1]
[27]:
# 先頭の3件の表示
x.head(3)
[27]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | |
---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 |
NumPy 入門で紹介したようなスライス記法を用いる際の先頭位置の省略も行えます。
[28]:
# すべての行の、先頭の列から末尾の列のひとつ手前までを選択
x = df.iloc[:, :-1]
[29]:
# 先頭の3件の表示
x.head(3)
[29]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | |
---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 |
行の数、列の数両方を複数選択した場合、データフレームオブジェクトが返ります。
[30]:
# 型の確認
type(x)
[30]:
pandas.core.frame.DataFrame
条件指定による要素の選択¶
次に値に対する条件を指定してデータの選択を行う方法を紹介します。
簡単のため、まず median_house_value
列を選択し、返ってきたシリーズオブジェクトに対して、比較演算子を使って各要素に対する条件を指定し、条件を満たすかどうかを全要素に対して調べた結果を取得してみましょう。
[31]:
# median_house_value 列を選択し、全要素に対し 70000 より大きいかどうかを計算
mask = df['median_house_value'] > 70000
[32]:
mask.head()
[32]:
0 False
1 True
2 True
3 True
4 False
Name: median_house_value, dtype: bool
このように、比較演算子の片方の辺にデータフレームやシリーズをおくと、指定された条件を満たすかどうかを全ての要素に対して計算することができます。 結果は、各要素が条件を満たすか、満たさないかを表す True
、False
が各要素の位置に格納されたデータフレームやシリーズとなります。 これをマスク (mask) と呼ぶことがあります。
そして、データフレームやシリーズも NumPy の ndarray と同様に、マスクを使って要素を選択することができます。 上の mask
を df
に []
を使って与えることで、指定した条件を満たす要素だけを取り出すことができます。
[33]:
# df[mask] の先頭 5 件を表示
df[mask].head()
[33]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 |
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 |
5 | -114.58 | 33.63 | 29.0 | 1387.0 | 236.0 | 671.0 | 239.0 | 3.3438 | 74000.0 |
6 | -114.58 | 33.61 | 25.0 | 2907.0 | 680.0 | 1841.0 | 633.0 | 2.6768 | 82400.0 |
複数の条件指定による要素の選択¶
複数の条件を組み合わせて要素を選択することも出来ます。 その場合は条件式を ()
でくくって用います。 論理和 (or) は |
、論理積 (and) は &
を用いて表します。
[34]:
# 70000 より小さい または 80000 より大きい
mask2 = (df['median_house_value'] < 70000) | (df['median_house_value'] > 80000)
[35]:
mask2.head()
[35]:
0 True
1 True
2 True
3 False
4 True
Name: median_house_value, dtype: bool
[36]:
df[mask2].head()
[36]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 |
4 | -114.57 | 33.57 | 20.0 | 1454.0 | 326.0 | 624.0 | 262.0 | 1.9250 | 65500.0 |
6 | -114.58 | 33.61 | 25.0 | 2907.0 | 680.0 | 1841.0 | 633.0 | 2.6768 | 82400.0 |
[37]:
# 70000 より大きい かつ 80000 より小さい
mask3 = (df['median_house_value'] > 70000) & (df['median_house_value'] < 80000)
[38]:
mask3.head()
[38]:
0 False
1 False
2 False
3 True
4 False
Name: median_house_value, dtype: bool
[39]:
df[mask3].head()
[39]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 |
5 | -114.58 | 33.63 | 29.0 | 1387.0 | 236.0 | 671.0 | 239.0 | 3.3438 | 74000.0 |
13 | -114.61 | 34.83 | 31.0 | 2478.0 | 464.0 | 1346.0 | 479.0 | 3.2120 | 70400.0 |
23 | -114.98 | 33.82 | 15.0 | 644.0 | 129.0 | 137.0 | 52.0 | 3.2097 | 71300.0 |
26 | -115.37 | 32.82 | 30.0 | 1602.0 | 322.0 | 1130.0 | 335.0 | 3.5735 | 71100.0 |
条件に当てはまる要素を調べる操作と、条件に当てはまる要素の選択まで、1 行にまとめて書くこともできます。
[40]:
df[(df['median_house_value'] > 70000) & (df['median_house_value'] < 80000)].head()
[40]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | |
---|---|---|---|---|---|---|---|---|---|
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 |
5 | -114.58 | 33.63 | 29.0 | 1387.0 | 236.0 | 671.0 | 239.0 | 3.3438 | 74000.0 |
13 | -114.61 | 34.83 | 31.0 | 2478.0 | 464.0 | 1346.0 | 479.0 | 3.2120 | 70400.0 |
23 | -114.98 | 33.82 | 15.0 | 644.0 | 129.0 | 137.0 | 52.0 | 3.2097 | 71300.0 |
26 | -115.37 | 32.82 | 30.0 | 1602.0 | 322.0 | 1130.0 | 335.0 | 3.5735 | 71100.0 |
条件指定による要素の置換¶
条件を指定して選択した要素に対し、値の書き換えを行うことができます。 例えば、median_house_value
列に対していくつかの条件を別々に調べ、それぞれの条件を満たしている場合に特定の値を持つような新しい列を df
に追加してみます。 median_house_value
が
60000 より小さい場合は 0
60000 以上 70000未満は 1
70000 以上 80000未満は 2
80000 以上は 3
となる値を持つ target
という列を追加します。
まず、何も値の入っていない target
という列を df
に追加します。
[41]:
# 新しい列 target を None で初期化
df['target'] = None
[42]:
df.head()
[42]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | target | |
---|---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 | None |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 | None |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 | None |
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 | None |
4 | -114.57 | 33.57 | 20.0 | 1454.0 | 326.0 | 624.0 | 262.0 | 1.9250 | 65500.0 | None |
target
という列の全ての要素は None
となっています。 この値を、条件指定によって書き換えます。
まず各条件に対応するマスクを作成します。
[43]:
mask1 = df['median_house_value'] < 60000
mask2 = (df['median_house_value'] >= 60000) & (df['median_house_value'] < 70000)
mask3 = (df['median_house_value'] >= 70000) & (df['median_house_value'] < 80000)
mask4 = df['median_house_value'] >= 80000
行や列を整数インデックスで選択する場合は df.iloc[]
を使用しましたが、列を名前で指定する場合には df.loc[]
を用います。 それでは、上で計算したマスクと名前による列指定を組み合わせて、各条件を満たす行の target
列の値を書き換えます。
[44]:
df.loc[mask1, 'target'] = 0
df.loc[mask2, 'target'] = 1
df.loc[mask3, 'target'] = 2
df.loc[mask4, 'target'] = 3
結果を確認してみましょう。
[45]:
# 先頭から 5 番目までを表示
df.head()
[45]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | target | |
---|---|---|---|---|---|---|---|---|---|---|
0 | -114.31 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 | 1 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 | 3 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 | 3 |
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 | 2 |
4 | -114.57 | 33.57 | 20.0 | 1454.0 | 326.0 | 624.0 | 262.0 | 1.9250 | 65500.0 | 1 |
欠損値の除去・補間¶
欠損値を含むデータの場合、一部の行の値が欠損している列に NaN
(Not a Number)、None
、NaT
(Not a Time) などが含まれる場合があります。 欠損値への対策としては、欠損値を含む行、または列を除去するか、欠損値を特定の値で補完するという方法が考えられます。
まずは、欠損値の除去の方法を紹介します。
[46]:
# 欠損値を人為的に作成
df.iloc[0, 0] = None
[47]:
# (0, 'longitude') の要素が NaN になっていることを確認
df.head(3)
[47]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | target | |
---|---|---|---|---|---|---|---|---|---|---|
0 | NaN | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 | 1 |
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 | 3 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 | 3 |
[48]:
# 欠損値のあるレコードを削除
df_dropna = df.dropna()
# 先頭から 3 件を表示
df_dropna.head(3)
[48]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | target | |
---|---|---|---|---|---|---|---|---|---|---|
1 | -114.47 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 | 3 |
2 | -114.56 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 | 3 |
3 | -114.57 | 33.64 | 14.0 | 1501.0 | 337.0 | 515.0 | 226.0 | 3.1917 | 73400.0 | 2 |
上の結果と見比べると、NaN
を含んでいた 0 行目のデータが取り除かれていることが分かります。
次に、平均を使った欠損値の補完を行ってみましょう。 まずは、補完に使用する平均値の計算を行います。
[49]:
mean = df.mean()
mean
[49]:
longitude -119.562417
latitude 35.625225
housing_median_age 28.589353
total_rooms 2643.664412
total_bedrooms 539.410824
population 1429.573941
households 501.221941
median_income 3.883578
median_house_value 207300.912353
target 2.808412
dtype: float64
計算した各列の値の平均が格納されている mean
を、df.fillna()
メソッドに渡すことで、mean
を用いた欠損値の補完を行うことができます。
[50]:
# 欠損値を mean で補完
df_fillna = df.fillna(mean)
# 先頭から 3 件を表示
df_fillna.head(3)
[50]:
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | target | |
---|---|---|---|---|---|---|---|---|---|---|
0 | -119.562417 | 34.19 | 15.0 | 5612.0 | 1283.0 | 1015.0 | 472.0 | 1.4936 | 66900.0 | 1 |
1 | -114.470000 | 34.40 | 19.0 | 7650.0 | 1901.0 | 1129.0 | 463.0 | 1.8200 | 80100.0 | 3 |
2 | -114.560000 | 33.69 | 17.0 | 720.0 | 174.0 | 333.0 | 117.0 | 1.6509 | 85700.0 | 3 |
0 行目のデータの longitude
列に、mean
の longitude
行の値が表示されていることが分かります。
今回は欠損値が 1 箇所にだけあるデータを用いましたが、df.dropna()
や df.fillna()
は、対象の全ての欠損値に対して上記のような操作を行うメソッドです。
ndarray とデータフレームを相互に変換¶
scikit-learn では、データフレームやシリーズをそのまま扱うことができます。 しかし、Chainer を含む他のライブラリやフレームワークではそのままでは扱うことができない場合もあります。 そこで、データフレームを NumPy の ndarray に変換する方法を紹介します。
まず、df
がデータフレームであることを確認します。
[51]:
type(df)
[51]:
pandas.core.frame.DataFrame
次に、df
の values
という属性の型を調べてみます。
[52]:
type(df.values)
[52]:
numpy.ndarray
NumPy の ndarray になっています。 データフレームやシリーズは、values
という属性に値を ndarray として格納しています。
[53]:
df.values
[53]:
array([[ nan, 3.4190e+01, 1.5000e+01, ..., 1.4936e+00,
6.6900e+04, 1.0000e+00],
[-1.1447e+02, 3.4400e+01, 1.9000e+01, ..., 1.8200e+00,
8.0100e+04, 3.0000e+00],
[-1.1456e+02, 3.3690e+01, 1.7000e+01, ..., 1.6509e+00,
8.5700e+04, 3.0000e+00],
...,
[-1.2430e+02, 4.1840e+01, 1.7000e+01, ..., 3.0313e+00,
1.0360e+05, 3.0000e+00],
[-1.2430e+02, 4.1800e+01, 1.9000e+01, ..., 1.9797e+00,
8.5800e+04, 3.0000e+00],
[-1.2435e+02, 4.0540e+01, 5.2000e+01, ..., 3.0147e+00,
9.4600e+04, 3.0000e+00]])
[54]:
type(df['longitude'])
[54]:
pandas.core.series.Series
[55]:
type(df['longitude'].values)
[55]:
numpy.ndarray
逆に、Python のリストや ndarray からシリーズやデータフレームを作ることもできます。 NumPy で乱数を要素にもつ ndarray を生成し、これをデータフレームに変換してみましょう。
pd.DataFrame
のインスタンス化の際に、data
引数に元にしたい ndarray を与えます。
[56]:
import numpy as np
# ndarray -> pd.DataFrame
df = pd.DataFrame(
data=np.random.randn(10, 10)
)
df
[56]:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.235076 | -0.025952 | 0.635551 | -1.233459 | 1.875983 | 0.471026 | -0.846990 | -0.727128 | 0.535281 | -0.662937 |
1 | 1.232096 | 0.327020 | 0.073412 | -0.291659 | -0.835771 | -1.806214 | -0.840970 | -0.731787 | -0.773722 | -0.657064 |
2 | 0.540820 | 0.140009 | 1.351297 | 2.709533 | 0.469056 | -0.573746 | -0.135772 | 0.352596 | 0.233631 | -0.658191 |
3 | 1.527199 | -1.129577 | 0.240729 | -0.352903 | -0.052596 | -0.013748 | -0.025188 | 1.117134 | -0.308465 | -1.696524 |
4 | -1.171764 | 0.503813 | 2.424457 | 0.262115 | 2.149916 | 0.984207 | -1.187516 | 1.079167 | -0.717449 | -0.347563 |
5 | 0.278999 | -0.892611 | 0.429661 | -2.511540 | 0.536308 | 0.811684 | 1.774007 | 1.392216 | 1.726091 | 0.561226 |
6 | 0.724094 | 0.804228 | 1.049159 | 0.348018 | -2.106214 | 0.185539 | -0.556945 | -1.541576 | -0.614728 | 0.809802 |
7 | -0.773019 | 1.327983 | 0.802475 | -1.562232 | -0.046259 | -0.536498 | -1.331944 | 0.280377 | -1.572351 | 1.142880 |
8 | 1.388867 | 0.551502 | -0.372442 | -0.093690 | 1.388269 | -1.969065 | 1.312570 | 1.141520 | -1.110659 | 0.704427 |
9 | -1.660362 | 0.081545 | 0.332048 | -1.252397 | 0.525961 | 0.352583 | 1.480100 | 1.378975 | -1.596351 | -0.642919 |