やりたいこと
国土交通省が公開している地価公示データを機械学習の特徴量に使いたい。
市区町村コードごとに1983年〜2021年までの各年の公示地価(m^2の単価)の平均を出します。
SHIFT-JIS CSVの読み込みと、DataFrameの整形についてメモを兼ねて解説します。
環境
Google Colabo -> 書いたコードはこちら
手順の目次
- 最新(令和3年)の公示CSVをダウンロード。GoogleDriveにアップします。
- DataFrameにCSVを読み込み
- DataFrameを整形
- DataFrameをCSVにGoogleDriveに出力(そのまま特徴量として学習データに取り込んでもよいです)
from google.colab import drive
drive.mount('/content/drive')
GoogleDriveをマウント。
認証URLが出てくるのでGoogleアカウントを選択して、キーをColaboに入力。
import numpy as np
import pandas as pd
from pandas import DataFrame, Series
# 公示地価格を取り込む(1983〜2021データ)
LP_PATH='~~~~~/LP/L01-2021P-2K.csv'
pl_df = pd.read_csv(LP_PATH,encoding="SHIFT_JIS")
NumPyとPandasを使うのでImportしておきます。
公示地価は2021年のCSVに1983年〜2021年までのデータが入っているので1つのCSVでOKです。
LP_PATH
はご自身のCSVをおいたDriveパスに読み替えてください。
pd.read_csv()
で読み込みます。
公示地価はShift-JISなので`encoding="SHIFT_JIS"'のパラメータを指定。
pl_df.info(verbose=True,null_counts=True)
読み込んだDataFrameをinfo()で確認します。
列数が多いとカラム名やデータタイプ、欠損値の数が出てこないので、
verbose=True
とnull_counts=True
のパラメータを指定します。
(列数が少ないと.info()
だけで情報が出てくるようです)
下記のように表示されます。
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 25993 entries, 0 to 25992
Data columns (total 119 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 経度 25993 non-null float64
1 緯度 25993 non-null float64
2 所在地コード 25993 non-null int64
3 用途 25993 non-null int64
4 連番 25993 non-null int64
5 年次 25993 non-null int64
6 前年所在地コード 25993 non-null int64
7 前年用途 25993 non-null int64
8 前年連番 25993 non-null int64
9 市区町村名 25993 non-null object
...
colm = (["経度","緯度","用途", "連番","年次","前年所在地コード","前年用途",
"前年連番","市区町村名","住居表示","行政","地積","利用の現況","利用状況表示",
"建物構造","施設","形状区分","間口(比率)","奥行(比率)","階層(地上)","階層(地下)",
"前面道路区分","前面道路の方位区分","前面道路の幅員","前面道路の駅前区分","前面道路の舗装状況","側道区分","側道方位区分",
"交通施設との近接区分","周辺の土地の利用の現況","駅名","駅距離","用途区分","防火区分",
"都市計画区分","森林区分","公園区分","建蔽率","容積率","共通地点区分","選定年次ビット",
"属性移動S59","属性移動S60","属性移動S61","属性移動S62","属性移動S63","属性移動H1","属性移動H2",
"属性移動H3","属性移動H4","属性移動H5","属性移動H6","属性移動H7","属性移動H8","属性移動H9",
"属性移動H10","属性移動H11","属性移動H12","属性移動H13","属性移動H14","属性移動H15",
"属性移動H16","属性移動H17","属性移動H18","属性移動H19","属性移動H20","属性移動H21",
"属性移動H22","属性移動H23","属性移動H24","属性移動H25","属性移動H26","属性移動H27",
"属性移動H28","属性移動H29","属性移動H30","属性移動H31","属性移動R2","属性移動R3"])
pl_df = pl_df.drop(columns=colm)
pl_df.info() #列数が少なくなると.info()だけでOK
市区町村コードと各年の公示地価以外の列を削除する。
# 0をNanに変換
def zero_to_nan(x):
if x == 0:
return np.nan
else:
return x
array = ['S58価格','S59価格','S60価格','S61価格','S62価格','S63価格','H1価格','H2価格',
'H3価格','H4価格','H5価格','H6価格','H7価格','H8価格','H9価格','H10価格',
'H11価格','H12価格','H13価格','H14価格','H15価格','H16価格','H17価格',
'H18価格','H19価格','H20価格','H21価格','H22価格','H23価格','H24価格',
'H25価格','H26価格','H27価格','H28価格','H29価格','H30価格','H31価格',
'R2価格','R3価格']
for arr in array:
pl_df.loc[:,arr] = pl_df.loc[:,arr].apply(zero_to_nan)
pl_df.head(2)
各年の公示価格のうち0となっている箇所をNaNにします。
(市町村ごとの各年の平均地価を出すときに含まれないようにするため)
#所在地コードでGroupbyして平均値を出す(NaNは平均値に含まれない)
pl_df = pl_df.groupby('所在地コード').mean(numeric_only=True)
pl_df.groupby('所在地コード')
で市区町村コード(=所在地コード)ごとにGroupByします。更に.mean()
でGroupごとの平均値を出します。
mean()のnumeric_only=True
のパラメータで、数値のみを対象にします(NaNを無視する)
# 価格をLogに変換
for arr in array:
pl_df.loc[:,arr] = np.log(pl_df.loc[:,arr])
桁数が大きくなると特徴量として扱いにくい気がしたので、Log10をかけてます。
np.log()
で変換。
# 列名の和暦を西暦に変更
colm_names = []
for num in range(1983,2022):
colm_names.append(num)
pl_df.columns = colm_names
和暦だと使いにくいので西暦に直してます。
Pythonのfor n in range(X,Y):
はX ≦ n < Y
を満たすときという条件です。
下限は≦、上限は<。
pl_df.head(2)
ちゃんと市区町村コードをキーに各年ごとの地価平均がLOGで出てたらOKです。
pl_df.to_csv('~~~/pl.csv')
.to_csv(PATH)
でCSV出力します。PATHは保存先のCSV名を指定。
以上です。