中島さん卒論_backup
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
[[技術資料]]
*目次 [#f3c34276]
#CONTENTS
*本研究の目的 [#cec342b3]
本研究の目的は,ヘドニック・アプローチにおける限界を克服...
正確で信頼性の高い評価手法を提供することである.ヘドニッ...
欠落変数のバイアス,交互作用効果および非線形効果の取り扱...
は不動産市場や消費財の価格評価において誤差を生じさせる要...
らの問題を解決するために,スパース推定法を活用した新たな...
従来のヘドニックモデルは,そのシンプルな線形構造と主要変...
で強力であったが,現実の市場では非線形な相互作用や高次の...
十分に捉えることができないことが多かった.また,異なる要...
の効果を正確に評価するためには,より複雑なモデルが求めら...
ElasticNetおよびその進化形であるAdaptiveElasticNet(AEN)を...
することを目指す.
ElasticNetはL1およびL2正則化を組み合わせることで,多重共...
と同時に,重要な変数の選択を行う能力を持つ.これにより,...
え,効果的な変数選択を実現できる.また,AENは,従来のElas...
データの特性に応じて正則化パラメータを動的に調整する.こ...
雑なデータ構造に対して非常に効果的であり,非線形性や交互...
できる.これにより,不動産市場や消費財の価格形成における...
え,価格予測の精度を向上させることが可能となる.
さらに,本研究では,従来の線形回帰モデルでは捉えきれなか...
効果をスパース推定法を活用することで反映させることができ...
技術と組み合わせることにより,より精緻な価格形成モデルが...
見過ごされがちな要因を捉えることが可能となる.例えば,不...
積の相互作用,消費財におけるブランド力と機能性の複合的影...
係性を反映させることで,より現実的な市場分析が行えるよう...
また,こうした高度な統計手法や機械学習技術の活用により,...
ローチを大きく強化することができる.特に,従来のアプロー...
格形成における微細な要因を,スパース推定を用いることで明...
評価を可能にする.これにより,不動産市場や消費財市場にお...
理解が深まり,実務的な応用に貢献することが期待される.
*使用するファイル [#pe64d1b6]
本研究で使用するファイルはすべてGoogleDriveにある。
&br;
user:iie.lab.tpu.2324@gmail.com
&br;
「マイドライブ」→「学生」→「24_o3中島」→「保存期間5年」→...
&br;
「引継ぎ用.zip」をダウンロードする。
&br;
ファイルの中身は以下のようになっている。
これを上から順に実行していく過程を以下の章に示す。
|フォルダ名|用途|ファイル名|ファイルの場所|
|データセットの作成|取引データの緯度経度変換(新しくデータ...
|データセットの作成|犯罪データの取得|get_crime_data.py|デ...
|データセットの作成|統計データなどの作成|hop_統計.ipynb|...
|データセットの作成|取引データのメッシュ変換|緯度経度.py|...
|データセットの作成|各データを取引データにまとめる|hop_メ...
|データセットの作成|犯罪場所との最短距離|distance.ipynb|...
|前処理|データセットの前処理|前処理.ipynb|前処理\前処理.i...
|変数選択|変数の選択とハイパーパラメータのチューニング|変...
|要因分析|選択された変数を用いたヘドニック・アプローチに...
|寄与率|選択された変数の価格に対する寄与率の算出|寄与率.i...
~
それぞれのコードを動かす際に初めに必要なファイル
前処理.ipynbを実行する前にデータセットの作成で作成された...
~
次に変数選択_削除.ipynbを実行する前に前処理で作成された削...
~
hedo_削除.ipynbを実行する前に削除_変数作成後.csvと選ばれ...
~
最後に寄与率.ipynbを実行する前に位置情報_削除.csv、削除_...
~
コードの変更点はディレクトリを変更するだけで大丈夫.
pythonのバージョンは12.0.0を用いる.
使用したモジュールのバージョンは下になります。(すべては...
#ref(module.png,,70%)
** 犯罪発生データの取得 [#k37ae06a]
「''get_crime_data.py''」を実行すると、富山県警が公開して...
&br;
**建築年数の算出 [#i8ed6a27]
建築年の年号を西暦にするために以下の式を書いた列を挿入す...
&br;
=IF(LEFT(M2,2)="令和", 2018 + MID(M2,3,LEN(M2)-3),
IF(LEFT(M2,2)="平成", 1988 + MID(M2,3,LEN(M2)-3),
IF(LEFT(M2,2)="昭和", 1925 + MID(M2,3,LEN(M2)-3), "エ...
次に取引時点から西暦を抜き出す。
&br;
=LEFT(W2,4)
そして、取引時点の西暦から建築年の西暦を引くことで建築年...
最後に残す列は建築年数のみ。~
**使用するデータ [#w637e5db]
実際の取引データはhttps://www.reinfolib.mlit.go.jp/realEs...
データセットの作成\data\estats_mesh、データセットの作成\d...
~
(https://www.e-stat.go.jp/gis/statmap-search?page=1&type=...
~
(https://www.e-stat.go.jp/gis/statmap-search?page=1&type=...
この二つのurlからメッシュごとのデータ。~
(https://www.e-stat.go.jp/stat-search/files?page=1&layout...
このurlから小地域ごとのデータを。~
** データの作成と収集(統計データや施設データ)[#x2b1cdcf]
「''hop_統計.ipynb''」を実行すると、取引データのメッシュ...
NAVITIMEからのスクレイピングや地図画像からのデータ作成を...
&br;
df_torihiki = pd.read_csv(
HERE / "df_housing_toyamacityメッシュ入り.csv",
index_col = "住所",
encoding = 'cp932')
メッシュコードを文字列として格納
&br;
meshes = df_torihiki["mesh_code"].astype(str).tolist()
作成する統計データは以下のようになる。
#ref(作成する統計データ.png,,)
&br;
import pandas as pd
# ここで上で指定した説明変数を生成
df_estats_block = pd.read_csv(
DATA_DIR / "estats_block.csv",
index_col = "KEY_CODE")
df_estats_mesh = pd.read_csv(
DATA_DIR / "estats_mesh.csv",
index_col = "KEY_CODE")
df_selected_block = pd.DataFrame()
df_selected_mesh = pd.DataFrame()
for line in stats_data_text.splitlines():
formula, label = line.rsplit(", ", 2)
if len( formula.split(" ") ) == 1:
if formula in df_estats_block.columns:
df_selected_block.loc[:, label] = df_estats_b...
if formula in df_estats_mesh.columns:
df_selected_mesh.loc[:, label] = df_estats_me...
elif len( formula.split(" ") ) >= 2:
contains_keys = re.findall("T.........", formula)
if contains_keys[0] in df_estats_block.columns:
for key in contains_keys:
formula = formula[:formula.find(key)] + "...
formula[formula.find(key) : formula.f...
"']" + formula[formula.find(key) ...
exec(f"df_selected_block.loc[:, '{label}'] = ...
elif contains_keys[0] in df_estats_mesh.columns: ...
for key in contains_keys:
formula = formula[:formula.find(key)] + "...
formula[formula.find(key) : formu...
"']" + formula[formula.find(k...
exec(f"df_selected_mesh.loc[:, '{label}'] = {...
df_selected_mesh = df_selected_mesh.fillna(0)
df_selected_block = df_selected_block.fillna(0)
df_selected_mesh
df_selected_block
&br;
# 次は施設データ.
# 統計データと同じで,カンマの左側の数字はNAVITIMEの...
# コンビニ一覧のURLは "https://www.navitime.co.jp/cat...
リIDは「0201」
building_data_text = '''\
0201, コンビニ
0802001, 駅
0805, 駐車場
0812, 駐輪場
0501, 金融機関
0603, 旅館
0608, ホテル
0202, スーパー
0205, ショッピングモール
0204, デパート
0502002, 警察署/交番
0504001, 小学校
0504002, 中学校
0504003, 高校
0504004, 大学
0504006, 保育園/幼稚園
0101, レジャー施設'''
# ここで,NAVITIMEからスクレイピング
df_buildings = pd.DataFrame()
def address2coords(address: str):
for trials in range(5):
res = requests.get(
urllib.parse.quote(
string = f"https://msearch.gsi.go.jp/addr...
safe = "://?="
)
)
if res.status_code == 200:
break
else:
time.sleep(5 * trials)
else:
raise Exception("国土地理院のジオコーディングAPI...
result = res.json()
time.sleep(0.5)
# サーバに負担をかけないように0.5秒待つ
if len(result) == 0:
return None
else:
return result[0]["geometry"]["coordinates"]
# 複数ある場合でも,0番目を採用
def get_building_info(category):
df_buildings = pd.DataFrame(columns = ["name", "addre...
for i in range(1, sys.maxsize):
# "while True"と同義
if i == 1:
url = f"https://www.navitime.co.jp/category/{...
else:
url = f"https://www.navitime.co.jp/category/{...
for trials in range(5):
res = requests.get(url)
if res.status_code == 200:
break
else:
time.sleep(5)
else:
break
# NAVITIME から 5 回連続で取得できなかったら...
soup = BeautifulSoup(res.text, "html.parser")
buildings = []
for element in soup.find_all(class_ = "spot-name-...
content = element.get_text()
buildings += [{"name": content}]
count = 0
for element in soup.find_all(class_ = "spot-detai...
content = element.get_text()
matches = re.findall(r"(北海道|東京都|大阪府|...
# 完璧ではないが、これで住所かを判定 ...
if len(matches) > 0:
address = content
coords = address2coords(address)
print(address, coords)
buildings[count]["address"] = address if ...
buildings[count]["lng"] = None
buildings[count]["lat"] = None
else:
buildings[count]["lng"] = coords[0]
buildings[count]["lat"] = coords[1] ...
count += 1
for building in buildings:
df_buildings = add_dict_to_df(building, df_bu...
return df_buildings
集めたデータを用いて不動産の取引が行われた場所の存在する...
**緯度経度からメッシュを格納 [#kea42b7d]
「''緯度経度.py''」を実行すると、地理情報(緯度・経度)か...
&br;
import pandas as pd
def latlon_to_mesh(lat, lon):
"""
緯度経度から9桁のメッシュコード(2分の1地域メッシュ)...
:param lat: 緯度(度)
:param lon: 経度(度)
:return: 9桁のメッシュコード(文字列)
"""
# 1次メッシュ
mesh1_lat = int(lat * 1.5)
mesh1_lon = int(lon - 100)
# 2次メッシュ
mesh2_lat = int((lat * 1.5 - mesh1_lat) * 8)
mesh2_lon = int((lon - 100 - mesh1_lon) * 8)
# 3次メッシュ
mesh3_lat = int(((lat * 1.5 - mesh1_lat) * 8 - mesh2_...
mesh3_lon = int(((lon - 100 - mesh1_lon) * 8 - mesh2_...
# 4次メッシュ(2分の1地域メッシュ)
mesh4_lat = int((((lat * 1.5 - mesh1_lat) * 8 - mesh2...
mesh4_lon = int((((lon - 100 - mesh1_lon) * 8 - mesh2...
# メッシュコードの組み立て(9桁になるよう修正)
mesh_code = f"{mesh1_lat:01}{mesh1_lon:01}{mesh2_lat:...
# 最後の2桁のみ取り出して、9桁にする
mesh_code = mesh_code[:9]
return mesh_code
# CSVファイルの読み込み
file_path = r"C:\Users
t011\Desktop\研究\富山取引のほう富山市のみ
\df_housing_toyamacity.csv"
df = pd.read_csv(file_path, encoding='utf-8')
# メッシュコードの計算
df["mesh_code"] = df.apply(lambda row: latlon_to_mesh...
cols = ["mesh_code"] + [col for col in df.columns if ...
df = df[cols]
# 結果のCSVを保存
output_path = r"C:\Users
t011\Desktop\研究\富山取引のほう富山市のみ
\df_housing_toyamacityメッシュ入り.csv"
df.to_csv(output_path, index=False)
print(f"処理完了: {output_path}")
#ref(作成されるデータ.png,,)
「''hop_メッシュ.ipynb''」を実行すると、メッシュコードご...
# メッシュGeoJsonを,分かりやすい形に直す
_meshes = {}
for mesh in meshes:
meshcode = mesh["properties"]["code"]
coords = mesh["geometry"]["coordinates"][0]
north = coords[1][1]
south = coords[0][1]
east = coords[2][0]
west = coords[0][0]
center = [(east + west) / 2, (north + south) / 2]
_meshes[meshcode] = {
"north": north,
"south": south,
"east": east,
"west": west,
"center": center
}
meshes = _meshes
# 犯罪データの座標から,どのグリッドセルに含まれるか...
# 「mesh_code」列に格納する
# 読み込んだメッシュGeoJsonに含まれない犯罪データは除外
df_temp = df_crimes[0:0].copy()
df_temp["mesh_code"] = None
for index, row in df_crimes.iterrows():
for meshcode, coords in meshes.items():
if ((coords["south"] <= row["latitude"] < coords[...
(coords["west"] <= row["longitude"] < coords[...
if not pd.isnull(row["datetime"]):
df_temp.loc[index] = pd.concat([
row,
pd.Series({
"mesh_code": meshcode
})
])
break
print(f"{df_crimes.index.get_loc(index)} / {len(df_cr...
df_crimes = df_temp.copy()
df_crimes["datetime"] = pd.to_datetime(df_crimes["dat...
# CSVファイルの読み込み
df_crimes = pd.read_csv(HERE / "犯罪_メッシュ入り.csv")
#メッシュごとに件数をカウント
mesh_counts = df_crimes['mesh_code'].value_counts().r...
mesh_counts.columns = ['mesh_code', '件数']
# 結果を表示
print(mesh_counts)
# 結果をCSVファイルに保存する場合
mesh_counts.to_csv(HERE / "犯罪_メッシュ件数.csv", in...
&br;
# 件数データ
df_number = pd.read_csv(
HERE / "犯罪_メッシュ件数.csv",
index_col = "mesh_code")
&br;
# 取引データ
df_torihiki = pd.read_csv(
HERE / "df_housing_toyamacityメッシュ入り.csv",
index_col = "mesh_code",
encoding = 'cp932')
&br;
# メッシュコードをキーとして結合
df_merged = pd.merge(df_torihiki, df_number, on='mesh...
suffixes=('', '_number'))
print(df_merged.head())
# 結果をCSVファイルに保存する場合
df_merged.to_csv(HERE / "取引_件数付き.csv", encoding...
&br;
df_mesh = pd.read_csv(
HERE / "data_by_mesh.csv",
index_col = "mesh_code",
encoding = "cp932")
&br;
df_torihiki2 = pd.read_csv(
HERE / "取引_件数付き.csv",
index_col = "mesh_code")
&br;
# メッシュコードでデータを結合
merged_df = pd.merge(df_torihiki2, df_mesh, on='mesh_...
print(merged_df.head())
merged_df.to_csv(HERE / "取引_統計データ付き.csv", in...
encoding='utf-8-sig')
犯罪発生率(件/250000)はhop_メッシュ.ipynbを行った後にcsv...
計算方法は=件数/250000で行う。~
件数列の空欄は0に統一する。~
取引_統計データ付き.csvに手動でdf_housing_toyamacityメッ...
#ref(統計データ.png,,20%)
「''distance.ipynb''」を実行すると、住宅地データ (取引_統...
import pandas as pd
from geopy.distance import geodesic
# ファイルを読み込む
df_housing = pd.read_csv("C:/Users/nt011/Desktop/統計...
の作成/取引_統計データ付き.csv")
df_crimes = pd.read_csv("C:/Users/nt011/Desktop/統計...
の作成/犯罪_メッシュ入り.csv")
print(df_housing.columns)
# 1. 住宅地データの緯度経度情報を抽出
df_housing['latitude'] = df_housing['緯度']
df_housing['longitude'] = df_housing['経度']
# 2. 犯罪データの緯度経度情報を抽出
df_crimes['latitude'] = df_crimes['latitude']
df_crimes['longitude'] = df_crimes['longitude']
# 3.最短距離を計算する関数
def calculate_min_distance(lat1, lon1, df_target, lat...
distances = df_target.apply(lambda row: geodesic((lat...
(row[lat_col], row[lon_col])).meters, axis=1)
return distances.min()
# 4. 各住宅地から犯罪発生場所までの最短距離を計算
df_housing['min_distance_to_crime'] = df_housing.appl...
calculate_min_distance(row['latitude'], row['longitud...
# 距離が0になる住宅地の行を表示
df_housing[df_housing['min_distance_to_crime'] == 0]
# 必要なカラムを選択して新しいDataFrameに保存
df_result = df_housing[['mesh_code', '住所', '経度', ...
'土地の形状', '間口', '延床面積(...
'用途', '前面道路:方位', '前面道...
'容積率(%)', '取引時点', '件数...
'65歳以上人口割合', '外国人人口割...
'非正規労働者割合', '最終学歴が中...
'居住年数5年未満の人口割合', '居...
'高層マンション割合', 'コンビニ',...
'保育園/幼稚園', 'レジャー施設',...
'ノード数(道路)', 'エッジ数(道...
# 結果の保存
df_result.to_csv('C:/Users/nt011/Desktop/統計正しいほ...
住宅地_犯罪_最短距離.csv', index=False, encoding='utf-8-...
#ref(最短.png,,20%)&br;
&br;
** データセットの前処理 [#u50edad0]
作成したデータセットを回帰分析がかけられる形に整える。
&br;
「''前処理.ipynb''」を実行し、「''住宅地_犯罪_最短距離.cs...
&br;
import pandas as pd
# CSVファイルのパス
file_path = r"C:\Users
t011\Desktop\統計正しいほう\前処理\住宅地_犯罪_最短距...
# CSVファイルを読み込む
df = pd.read_csv(file_path)
# 欠損値を含む行を削除
df = df.dropna()
# 「建築年数」列に `-1` または `"VALUE"` を含む行を削除
df = df[~df["建築年数"].astype(str).isin(["-1", "#VAL...
# 「最寄駅:距離(分)」の値を変換
replace_dict = {
"30分~60分": 45,
"1H~1H30": 75,
"1H30~2H": 105
}
df["最寄駅:距離(分)"] = df["最寄駅:距離(分)"].r...
# クリーンなデータを新しいCSVファイルとして保存
output_path = r"C:\Users
t011\Desktop\統計正しいほう\前処理\住宅地_犯罪_最短距...
df.to_csv(output_path, index=False, encoding='utf-8-s...
print("データ処理完了: 欠損値と指定された異常値を削除...
print(f"新しいCSVファイルが {output_path} に保存され...
生成した「''住宅地_犯罪_最短距離_欠損値削除後.csv''」から...
◆不動産取引価格~
https://www.reinfolib.mlit.go.jp/realEstatePrices/~
~
このurlの制度と用語のページを参考にして変換を行う。
#ref(建物の構造.png,,30%)
&br;
import pandas as pd
# CSVファイルのパス
file_path = "C:/Users/nt011/Desktop/統計正しいほう/前...
離_欠損値削除後.csv"
# CSVファイルを読み込む
df = pd.read_csv(file_path)
# 外れ値を検出する連続変数のカラムリスト
continuous_columns = [
"最寄駅:距離(分)", "取引価格(総額)", "面積(㎡)...
"間口", "延床面積(㎡)", "建築年数", "前面道路:幅員...
"建ぺい率(%)", "容積率(%)", "犯罪発生率(件/2500...
"18歳未満人口割合", "65歳以上人口割合", "外国人人口割...
"単身世帯割合", "核家族世帯割合", "正規労働者割合", "...
"最終学歴が中学以下の人口割合", "最終学歴が高校の人口...
"居住年数5年未満の人口割合", "居住年数が20年以上の人...
"アパート・低中層マンション割合", "高層マンション割合...
"建物の面積比率", "水の面積比率", "空き地の面積比率",...
"エッジ数(道路)", "密度(道路)", "平均次数(道路)...
]
# データ型を数値に変換(エラーが出たらNaNにする)
for column in continuous_columns:
if column in df.columns:
df[column] = pd.to_numeric(df[column], errors='co...
# 外れ値を持つ行のインデックスを格納するリスト
outlier_indices = set()
# 外れ値の検出と削除
for column in continuous_columns:
if column in df.columns:
# 欠損値を除外
df_clean = df[column].dropna()
# IQR(四分位範囲)の計算
Q1 = df_clean.quantile(0.25)
Q3 = df_clean.quantile(0.75)
IQR = Q3 - Q1
# 外れ値の閾値を設定
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 外れ値のインデックスを取得
outliers = df[(df[column] < lower_bound) | (df[co...
outlier_indices.update(outliers.index)
# 外れ値の行を削除
df_cleaned = df.drop(index=outlier_indices)
# 結果を新しいCSVに保存
output_path = "C:/Users/nt011/Desktop/統計正しいほう/...
df_cleaned.to_csv(output_path, encoding="utf-8-sig", ...
print(f"外れ値を削除したデータを {output_path} に保存...
print(f"削除した行数: {len(outlier_indices)}")
print(f"最終データの行数: {df_cleaned.shape[0]}")
それぞれのカラムの要素を必要に応じてダミー変数化した後、...
import pandas as pd
# CSVファイルを読み込み
df_data = pd.read_csv("C:/Users/nt011/Desktop/統計正...
# カラム名を取得
columns = df_data.columns.tolist()
# 建物の構造列に「RC」がある場合、「鉄筋コンクリート...
df_data['建物の構造'] = df_data['建物の構造'].replace...
# 最寄り駅名を二値化(列名を「最寄り駅名_富山」に変更)
index = columns.index("最寄駅:名称") # 変換前の位置...
df_data.insert(index + 1, '最寄り駅名_富山', df_data[...
df_data = df_data.drop(columns=['最寄駅:名称']) # ...
# 都市計画を二値化(列名を「都市計画_市街化調整区域」...
index = columns.index("都市計画")
df_data.insert(index + 1, '都市計画_市街化調整区域', ...
df_data = df_data.drop(columns=['都市計画'])
# 土地の形状を二値化(列名を「土地の形状_不整形」に変...
index = columns.index("土地の形状")
df_data.insert(index + 1, '土地の形状_不整形', df_dat...
df_data = df_data.drop(columns=['土地の形状'])
# 用途を二値化(列名を「用途_住宅」に変更)
index = columns.index("用途")
df_data.insert(index + 1, '用途_住宅', df_data['用途'...
df_data = df_data.drop(columns=['用途'])
# 建物の構造を二値化(列名を「建物の構造_木造」に変更)
index = columns.index("建物の構造")
df_data.insert(index + 1, '建物の構造_木造', df_data[...
df_data = df_data.drop(columns=['建物の構造'])
# 「前面道路:方位」のダミー変数化(基準値「北西」を0...
index = columns.index("前面道路:方位") # 変換前の位...
dummies = pd.get_dummies(df_data['前面道路:方位'], p...
# 基準値は削除
baseline_value = '北西'
if f'前面道路:方位_{baseline_value}' in dummies.colu...
dummies = dummies.drop(columns=[f'前面道路:方位_{bas...
# 挿入(前面道路:方位のダミー変数)
ordered_dummies = ['前面道路:方位_西', '前面道路:方...
'前面道路:方位_南', '前面道路:方位_...
# 順番に従って挿入
for col in ordered_dummies:
if col in dummies.columns:
df_data.insert(index + 1, col, dummies[col])
# 「前面道路:種類」のダミー変数化
road_types = ['市道', '私道', '県道']
# 順番を指定してダミー変数を挿入
for road in road_types:
df_data.insert(index + 1, f'前面道路:種類_{road}', (...
# 元の「前面道路:方位」および「前面道路:種類」列を...
df_data = df_data.drop(columns=['前面道路:方位', '前...
# 確認用にダミー変数化後のデータフレームを表示
print(df_data.head())
# ダミー変数化後のデータを保存
df_data.to_csv("C:/Users/nt011/Desktop/統計正しいほう...
index=False, encoding='utf-8-sig')
print("ダミー変数変換完了!データが保存されました。")
#ref(ダミー.png,,20%)
&br;
連続変数とダミー変数を手動で分類し、連続変数のみ二次項の...
交互作用項の作成したデータフレームを保存した「''削除_変数...
import pandas as pd
import numpy as np
from itertools import combinations
# CSVファイルのパスを指定
file_path = "C:/Users/nt011/Desktop/統計正しいほう/前...
# UTF-8で読み込む
df = pd.read_csv(file_path)
# データの先頭を表示
print(df.head())
# 連続変数とダミー変数を手動で分類
continuous_vars = [
'最寄駅:距離(分)', '面積(㎡)', '間口', '延床面積...
'建ぺい率(%)', '容積率(%)', '犯罪発生率(件/2500...
'65歳以上人口割合', '外国人人口割合', '世帯数', '単身...
'正規労働者割合', '非正規労働者割合', '最終学歴が中学...
'最終学歴が大学以上の人口割合', '居住年数5年未満の人...
'一戸建て割合', 'アパート・低中層マンション割合', 'コ...
'金融機関', '旅館', 'ホテル', 'スーパー', 'ショッピン...
'デパート', '警察署/交番', '小学校', '中学校', '高校...
'レジャー施設','道路の面積比率', '建物の面積比率', '...
'ノード数(道路)', 'エッジ数(道路)', '密度(道路)...
]
# ダミー変数をリストとして定義
dummy_vars = [
'最寄り駅名_富山','土地の形状_不整形', '建物の構造_木...
'用途_住宅', '前面道路:方位_北', '前面道路:方位_北...
'前面道路:方位_南', '前面道路:方位_南東',
'前面道路:方位_南西', '前面道路:方位_東', '前面道路...
'前面道路:種類_市道', '前面道路:種類_県道', '前面道...
'都市計画_市街化調整区域'
]
# 二次項の作成(連続変数のみ)
for var in continuous_vars:
df[f'{var}^2'] = df[var] ** 2
# 交互作用項の作成
# 連続変数 × 連続変数
for var1, var2 in combinations(continuous_vars, 2):
df[f'{var1}×{var2}'] = df[var1] * df[var2]
# ダミー変数 × 連続変数
for dummy_var in dummy_vars:
for cont_var in continuous_vars:
df[f'{dummy_var}×{cont_var}'] = df[dummy_var] * d...
# ダミー変数 × ダミー変数
for var1, var2 in combinations(dummy_vars, 2):
df[f'{var1}×{var2}'] = df[var1] * df[var2]
# CSVに保存
output_path = "C:/Users/nt011/Desktop/統計正しいほう/...
df.to_csv(output_path, index=False, encoding='utf-8-s...
print(f"処理が完了しました。生成されたデータは {outpu...
#ref(交互作用項.png,,20%)
&br;
*変数選択 [#u9327c42]
***Elastic Netとは [#d2ec2870]
Elastic Netは、L1 正則化(Lasso)と L2 正則化(Ridge)の...
Lasso(L1正則化):L1正則化は、回帰モデルの係数の一部をゼ...
&br;
Ridge(L2正則化):L2正則化は、回帰モデルの係数を小さくす...
&br;
StandardScaler() を用いて X(説明変数)と y(目的変数)を...
Adaptive Elastic Netを用いて土地の価格に影響する重要な特...
#ref(式.png,,50%)
***手順 [#d2ec2870]
「''変数選択__削除.ipynb''」を実行すると、重要な変数のみ...
import numbers
import warnings
import cvxpy
import numpy as np
from asgl import ASGL
from sklearn.base import MultiOutputMixin
from sklearn.base import RegressorMixin
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import ElasticNet
from sklearn.linear_model._coordinate_descent import ...
from sklearn.utils import check_X_y
from sklearn.utils.validation import check_is_fitted
class AdaptiveElasticNet(ASGL, ElasticNet, MultiOutpu...
"""
Objective function and parameters as described with m...
to allow alpha1, alpha2, l1_ratio1, and l1_ratio2 cus...
"""
def __init__(
self,
alpha1=0.021544346900318846, # First-stage Elas...
alpha2=0.0009443498043343188, # Second-stage Ela...
*,
l1_ratio1=0.8889, # First-stage ElasticNet L1 ra...
l1_ratio2=0.778, # Second-stage ElasticNet L1 ra...
gamma=0.5, # Weight adjustment exponent
fit_intercept=True,
precompute=False,
max_iter=10000,
copy_X=True,
solver=None,
tol=None,
positive=False,
positive_tol=1e-3,
random_state=None,
eps_coef=1e-6,
verbose=True
):
params_asgl = dict(model="lm", penalization="asgl")
if solver is not None:
params_asgl["solver"] = solver
if tol is not None:
params_asgl["tol"] = tol
super().__init__(**params_asgl)
self.alpha1 = alpha1
self.alpha2 = alpha2
self.l1_ratio1 = l1_ratio1
self.l1_ratio2 = l1_ratio2
self.gamma = gamma
self.fit_intercept = fit_intercept
self.max_iter = max_iter
self.precompute = precompute
self.copy_X = copy_X
self.positive = positive
self.positive_tol = positive_tol
self.random_state = random_state
self.eps_coef = eps_coef
self.verbose = verbose
if not self.fit_intercept:
raise NotImplementedError
def fit(self, X, y, check_input=True):
if check_input:
X_copied = self.copy_X and self.fit_intercept
X, y = self._validate_data(
X,
y,
accept_sparse="csc",
order="F",
dtype=[np.float64, np.float32],
copy=X_copied,
multi_output=True,
y_numeric=True,
)
# 第一段階の ElasticNet 実行
enet_model_1 = self.elastic_net(self.l1_ratio1, a...
enet_model_1.fit(X, y)
enet_coef = enet_model_1.coef_
# 重みの計算
weights = 1.0 / (np.maximum(np.abs(enet_coef), se...
# 第二段階の最適化
self.coef_, self.intercept_ = self._optimize_seco...
# モデル属性を格納
self.enet_coef_ = enet_coef
self.weights_ = weights
return self
def predict(self, X):
check_is_fitted(self, ["coef_", "intercept_"])
return super(ElasticNet, self).predict(X)
def elastic_net(self, l1_ratio, **params):
"""
Create an ElasticNet model with the specified par...
"""
elastic_net = ElasticNet(l1_ratio=l1_ratio)
for k, v in self.get_params().items():
try:
elastic_net = elastic_net.set_params(**{k...
except ValueError:
pass # Ignore parameters not supported b...
elastic_net = elastic_net.set_params(**params)
return elastic_net
def _optimize_second_stage(self, X, y, weights):
"""
Perform second-stage optimization with adaptive w...
Returns
-------
coef : np.array, shape (n_features,)
intercept : float
"""
n_samples, n_features = X.shape
beta_variables = [cvxpy.Variable(n_features)]
model_prediction = 0.0
if self.fit_intercept:
beta_variables = [cvxpy.Variable(1)] + beta_v...
ones = cvxpy.Constant(np.ones((n_samples, 1)))
model_prediction += ones @ beta_variables[0]
# モデル予測
model_prediction += X @ beta_variables[1]
error = cvxpy.sum_squares(y - model_prediction) /...
l1_coefs = self.alpha2 * self.l1_ratio2
# 第二段階の正則化項
l1_penalty = cvxpy.Constant(l1_coefs * weights) @...
beta_variables[1]
)
l2_penalty = (
cvxpy.Constant(self.alpha1 * (1 - self.l1_rat...
* cvxpy.sum_squares(beta_variables[1])
)
constraints = [b >= 0 for b in beta_variables] if...
# 最適化問題の定義
problem = cvxpy.Problem(
cvxpy.Minimize(error + l1_penalty + l2_penalt...
constraints=constraints
)
problem.solve(solver="OSQP", max_iter=self.max_it...
if problem.status != "optimal":
raise ConvergenceWarning(
f"Solver did not reach optimum (Status: {...
)
beta_sol = np.concatenate([b.value for b in beta_...
beta_sol[np.abs(beta_sol) < self.tol] = 0
intercept, coef = beta_sol[0], beta_sol[1:]
coef = np.maximum(coef, 0) if self.positive else ...
return coef, intercept
from sklearn.linear_model import ElasticNetCV
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import make_regression
import numpy as np
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.preprocessing import StandardScaler
# CSVファイルのパスを指定してください
file_path = "C:/Users/nt011/Desktop/統計正しいほう/変...
# CSVファイルの読み込み
df = pd.read_csv(file_path) # 文字コードが異なる場合...
# 特徴量とターゲットの分割
X = df.drop(columns=['取引価格(㎡単価)']) # 取引価...
y = df['取引価格(㎡単価)'] # ターゲット変数
# 🔥 標準化の実施
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X) # Xの標準化
y_scaled = scaler_y.fit_transform(y.values.reshape(-1...
# データ分割
X_train, X_test, y_train, y_test = train_test_split(X...
test_size=0.2, random_state=42)
# 訓練データの一部を使用
X_sample, _, y_sample, _ = train_test_split(X_train, ...
random_state=42)
# 第一段階: ElasticNetCVを使用した最適パラメータの導出
enet_cv = ElasticNetCV(
l1_ratio=np.linspace(0.0001, 1, 25), # l1_ratioの候補
alphas=np.logspace(-5, 0, 25), # alphaの候補
cv=5, # 交差検証の分割数
random_state=42,
n_jobs=-1,
verbose=1
)
enet_cv.fit(X_train, y_train)
# 第一段階の最適パラメータと係数を取得
alpha1_opt = enet_cv.alpha_
l1_ratio1_opt = enet_cv.l1_ratio_
enet_coef = enet_cv.coef_
print(f"第一段階の最適パラメータ: alpha1={alpha1_opt}...
{l1_ratio1_opt}")
# ベストパラメータをalpha2とl1_ratio2でそれぞれ格納
best_alpha2 = best_params['alpha2']
best_l1_ratio2 = best_params['l1_ratio2']
print(best_alpha2)
print(best_l1_ratio2)
ASGLとElasticNetを組み合わせたAdaptiveElasticNetクラスを...
import numbers
import warnings
import cvxpy
import numpy as np
from asgl import ASGL
from sklearn.base import MultiOutputMixin
from sklearn.base import RegressorMixin
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import ElasticNet
from sklearn.linear_model._coordinate_descent import ...
from sklearn.utils import check_X_y
from sklearn.utils.validation import check_is_fitted
class AdaptiveElasticNet(ASGL, ElasticNet, MultiOutpu...
"""
Objective function and parameters as described with m...
to allow alpha1, alpha2, l1_ratio1, and l1_ratio2 cus...
"""
def __init__(
self,
alpha1=0.01333521432163324, # 第一段階で得られ...
alpha2=0.034807005884284134, # Second-stage Elas...
*,
l1_ratio1=1, # First-stage ElasticNet L1 ratio
l1_ratio2=0.1667499999999998, # Second-stage Ela...
gamma=0.5, # Weight adjustment exponent
fit_intercept=True,
precompute=False,
max_iter=10000,
copy_X=True,
solver=None,
tol=None,
positive=False,
positive_tol=1e-3,
random_state=None,
eps_coef=1e-6,
verbose=True
):
params_asgl = dict(model="lm", penalization="asgl")
if solver is not None:
params_asgl["solver"] = solver
if tol is not None:
params_asgl["tol"] = tol
super().__init__(**params_asgl)
self.alpha1 = alpha1
self.alpha2 = alpha2
self.l1_ratio1 = l1_ratio1
self.l1_ratio2 = l1_ratio2
self.gamma = gamma
self.fit_intercept = fit_intercept
self.max_iter = max_iter
self.precompute = precompute
self.copy_X = copy_X
self.positive = positive
self.positive_tol = positive_tol
self.random_state = random_state
self.eps_coef = eps_coef
self.verbose = verbose
if not self.fit_intercept:
raise NotImplementedError
def fit(self, X, y, check_input=True):
if check_input:
X_copied = self.copy_X and self.fit_intercept
X, y = self._validate_data(
X,
y,
accept_sparse="csc",
order="F",
dtype=[np.float64, np.float32],
copy=X_copied,
multi_output=True,
y_numeric=True,
)
# 第一段階の ElasticNet 実行
enet_model_1 = self.elastic_net(self.l1_ratio1, a...
enet_model_1.fit(X, y)
enet_coef = enet_model_1.coef_
# 重みの計算
weights = 1.0 / (np.maximum(np.abs(enet_coef), se...
# 第二段階の最適化
self.coef_, self.intercept_ = self._optimize_seco...
# モデル属性を格納
self.enet_coef_ = enet_coef
self.weights_ = weights
return self
def predict(self, X):
check_is_fitted(self, ["coef_", "intercept_"])
return super(ElasticNet, self).predict(X)
def elastic_net(self, l1_ratio, **params):
"""
Create an ElasticNet model with the specified par...
"""
elastic_net = ElasticNet(l1_ratio=l1_ratio)
for k, v in self.get_params().items():
try:
elastic_net = elastic_net.set_params(**{k...
except ValueError:
pass # Ignore parameters not supported b...
elastic_net = elastic_net.set_params(**params)
return elastic_net
def _optimize_second_stage(self, X, y, weights):
"""
Perform second-stage optimization with adaptive w...
Returns
-------
coef : np.array, shape (n_features,)
intercept : float
"""
n_samples, n_features = X.shape
beta_variables = [cvxpy.Variable(n_features)]
model_prediction = 0.0
if self.fit_intercept:
beta_variables = [cvxpy.Variable(1)] + beta_v...
ones = cvxpy.Constant(np.ones((n_samples, 1)))
model_prediction += ones @ beta_variables[0]
# モデル予測
model_prediction += X @ beta_variables[1]
error = cvxpy.sum_squares(y - model_prediction) /...
l1_coefs = self.alpha2 * self.l1_ratio2
# 第二段階の正則化項
l1_penalty = cvxpy.Constant(l1_coefs * weights) @...
beta_variables[1]
)
l2_penalty = (
cvxpy.Constant(self.alpha1 * (1 - self.l1_rat...
* cvxpy.sum_squares(beta_variables[1])
)
constraints = [b >= 0 for b in beta_variables] if...
# 最適化問題の定義
problem = cvxpy.Problem(
cvxpy.Minimize(error + l1_penalty + l2_penalt...
constraints=constraints
)
problem.solve(solver="OSQP", max_iter=self.max_it...
if problem.status != "optimal":
raise ConvergenceWarning(
f"Solver did not reach optimum (Status: {...
)
beta_sol = np.concatenate([b.value for b in beta_...
beta_sol[np.abs(beta_sol) < self.tol] = 0
intercept, coef = beta_sol[0], beta_sol[1:]
coef = np.maximum(coef, 0) if self.positive else ...
return coef, intercept
import pandas as pd
from sklearn.preprocessing import StandardScaler
# CSVファイルのパスを指定してください
file_path = "C:/Users/monda/OneDrive/デスクトップ/統...
削除_変数作成後.csv"
# CSVファイルの読み込み
df = pd.read_csv(file_path) # 文字コードが異なる場合...
コーディングに変更してください
# 特徴量とターゲットの分割
X = df.drop(columns=['取引価格(㎡単価)']) # 取引価...
離
y = df['取引価格(㎡単価)'] # ターゲット変数
# 🔥 標準化の実施
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X) # Xの標準化
y_scaled = scaler_y.fit_transform(y.values.reshape(-1...
準化
model = AdaptiveElasticNet()
model.fit(X_scaled, y_scaled)
# 係数の表示(重要な特徴量を確認)
coef = model.coef_
print("特徴量の係数:", coef)
# 係数がゼロでない特徴量を選定
selected_features = X.columns[coef != 0]
print("選定された特徴量:", selected_features)
# 係数と特徴量名をデータフレームに変換
selected_features_df = pd.DataFrame({
'Feature': X.columns,
'Coefficient': coef
})
# 係数がゼロでない特徴量のみをフィルタリング
selected_features_df = selected_features_df[selected_...
# CSVファイルとして保存
output_file_path = "選ばれた変数.csv" # 保存先を指定...
selected_features_df.to_csv(output_file_path, index=F...
# 日本語対応のエンコーディング
print(f"選定された特徴量と係数を {output_file_path} ...
#ref(変数選択.png,,50%)
&br;
AENの数式は以下のようなものを扱う。そして、今回行ったハイ...
AENの推計は,二段階で行われる.まず,予備推計としてEN で...
うえで,係数の絶対値が小さい変数に対してより強い罰則を与...
項を変数ごとに調整したうえで,改めてEN を実施する.
#ref(AEN.png,,150%)
#ref(ハイパーパラメータ.png,,150%)
選択された変数は以下のようになる
#ref(選ばれた変数.png,,)
*要因分析 [#w249dca6]
***手順 [#d20580fd]
「''hedo.ipynb''」を実行すると、有意水準に基づいて有意性...
import pandas as pd
# Excelファイルを読み込み
file_path = "c:/Users/nt011/Desktop/統計正しいほう/要...
除.csv"
df = pd.read_csv(file_path)
# 住所が含まれている列を特定して、住所ごとの出現回数...
address_column = '住所' # 住所列の名前がわからない場...
さい
if address_column in df.columns:
address_counts = df[address_column].dropna().value_co...
現回数を集計
# 出現回数をデータフレームに変換
address_counts_df = address_counts.reset_index()
address_counts_df.columns = ['住所', '出現回数'] # ...
# 結果をCSVファイルに書き出し
output_file = "c:/Users/nt011/Desktop/統計正しいほう/...
削除.csv"
address_counts_df.to_csv(output_file, index=False, en...
# UTF-8エンコーディングで保存
print(f"住所ごとの出現回数がCSVファイルに保存されまし...
else:
print("住所列が見つかりません")
回帰係数、t値、p値、有意性を格納したリストを「''回帰分析...
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
# ファイルパスの指定
selected_features_path = "選ばれた変数_削除.csv"
all_data_path = "c:/Users/nt011/Desktop/統計正しいほ...
成後.csv"
location_data_path = "c:/Users/nt011/Desktop/統計正し...
報_削除.csv"
output_data_path = "選択された特徴量とデータ_削除.csv"
# 選定された変数のCSVファイルを読み込み
selected_features_df = pd.read_csv(selected_features_...
selected_features = selected_features_df['Feature'].t...
# 元データを再度読み込み
all_data_df = pd.read_csv(all_data_path)
# 選定された説明変数と目的変数を抽出
df = all_data_df[selected_features + ['取引価格(㎡単...
# 位置情報データを読み込み
location_df = pd.read_csv(location_data_path, usecols...
# 元データと位置情報を結合(共通のキーがある場合)
df = pd.concat([df, location_df], axis=1)
# 統合データをCSVファイルとして保存
df.to_csv(output_data_path, index=False, encoding='ut...
print(f"選定された変数と位置情報を含むデータを {outpu...
した。")
import pandas as pd
# ファイルパス
count_file = "c:/Users/nt011/Desktop/統計正しいほう/...
data_file = "C:/Users/nt011/Desktop/統計正しいほう/要...
output_file = "C:/Users/nt011/Desktop/統計正しいほう/...
# CSVファイルの読み込み
count_df = pd.read_csv(count_file, encoding='utf-8-si...
data_df = pd.read_csv(data_file, encoding='utf-8-sig')
# 住所列の名前
address_column = '住所'
# 緯度・経度を除外(該当カラムがある場合)
drop_columns = ['緯度', '経度']
data_df = data_df.drop(columns=[col for col in drop_c...
data_df.columns])
# 住所の出現回数をデータに統合
merged_df = data_df.merge(count_df, on=address_column...
# 出現回数の多い順にソート
sorted_df = merged_df.sort_values(by='出現回数', asce...
# ソート済みデータをCSVに保存
sorted_df.to_csv(output_file, encoding='utf-8-sig', i...
print(f"ソート済みデータを {output_file} に保存しまし...
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
import statsmodels.api as sm
# データの読み込み
file_path = "C:/Users/nt011/Desktop/統計正しいほう/要...
data = pd.read_csv(file_path)
# 目的変数と説明変数の設定
y = data['取引価格(㎡単価)'] # 取引価格を目的変数に
X = data.drop(columns=['取引価格(㎡単価)', '住所'])...
# 🔥 標準化の実施
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X) # Xの標準化
y_scaled = scaler_y.fit_transform(y.values.reshape(-1...
準化
# 線形回帰モデルの作成
model = LinearRegression()
model.fit(X_scaled, y)
# 回帰分析の結果を表示
X_scaled_with_const = sm.add_constant(X_scaled) # 定...
ols_model = sm.OLS(y, X_scaled_with_const).fit()
# 必要な情報を抽出
r_squared = ols_model.rsquared # 決定係数
coefficients = ols_model.params # 回帰係数(定数項も...
t_values = ols_model.tvalues # t値(定数項も含む)
p_values = ols_model.pvalues # p値(有意水準を判定す...
variable_names = ['定数項'] + list(X.columns)
# 有意水準に基づいて有意性を判定する関数
def significance(p_value):
if p_value < 0.01:
return "1% 有意"
elif p_value < 0.05:
return "5% 有意"
elif p_value < 0.10:
return "10% 有意"
else:
return "有意でない"
# 結果を格納するリスト
results = []
# 回帰係数、t値、p値、有意性をリストに格納
for var_name, coef, t_val, p_val in zip(variable_name...
t_values, p_values):
significance_level = significance(p_val)
results.append([var_name, coef, t_val, p_val, signifi...
# 結果をDataFrameに変換
results_df = pd.DataFrame(results, columns=["変数", "...
値", "有意性"])
# 予測値の計算
data["標準化予測取引価格(㎡単価)"] =
ols_model.predict(X_scaled_with_const)
data["標準化実測取引価格(㎡単価)"] = y_scaled
# **結果を表示**
print("
==== 回帰分析結果 ====")
print(f"決定係数 (R^2): {r_squared:.4f}
")
print(results_df)
# 予測結果を含めたデータを保存
predicted_output_file_path = "C:/Users/nt011/Desktop/...
析/予測結果_削除.csv"
data.to_csv(predicted_output_file_path, index=False, ...
# CSVファイルとして保存
output_file_path = "C:/Users/nt011/Desktop/統計正しい...
結果_削除.csv"
results_df.to_csv(output_file_path, index=False, enco...
print(f"回帰分析結果が{output_file_path}に保存されま...
#ref(ヘドニック.png,,50%)
*寄与率の算出 [#u04f9941]
寄与率は下の数式と変数で算出を行う。~
実行を行う前に寄与率フォルダ内に町ごとの寄与率フォルダを...
寄与率.ipynbを上から実行する。~
#ref(寄与率_数式.png,,)
#ref(寄与率_変数.png,,)
AENで選ばれた一次項、二次項、交互作用項から一次項、二次項...
選ばれた変数によって交互作用項の計算と不要な変数の削除の...
具体的には面積(㎡)×建ぺい率(%)が選ばれた場合には、交...
&br;
import pandas as pd
import os
# データの読み込み
data_file = "C:/Users/tn011/Desktop/統計正しいほう/寄...
除.csv"
location_file = "C:/Users/tn011/Desktop/統計正しいほ...
度経度_削除.csv"
output_file = "C:/Users/tn011/Desktop/統計正しいほう/...
削除.csv"
df = pd.read_csv(data_file)
location_df = pd.read_csv(location_file)
# 交互作用項の計算
交互作用項 = [
('最寄駅:距離(分)', 'レジャー施設'),
('最寄駅:距離(分)', '密度(道路)'),
('面積(㎡)', '前面道路:幅員(m)'),
('居住年数5年未満の人口割合', '小学校'),
('一戸建て割合', 'min_distance_to_crime'),
('アパート・低中層マンション割合', 'min_distance_to_c...
('ホテル', '建物の面積比率'),
('デパート', '平均次数(道路)'),
('中学校', '建物の面積比率'),
('保育園/幼稚園', 'min_distance_to_crime'),
('最寄り駅名_富山', '最終学歴が大学以上の人口割合'),
('土地の形状_不整形', '居住年数が20年以上の人口割合'),
('建物の構造_木造', '面積(㎡)'),
('建物の構造_木造', '高校'),
('用途_住宅', '延床面積(㎡)'),
('前面道路:方位_南東', 'エッジ数(道路)'),
('都市計画_市街化調整区域', '中学校'),
]
# 交互作用項を計算し、列を追加
for var1, var2 in 交互作用項:
df[f'{var1}×{var2}'] = df[var1] * df[var2]
# 不要な要素のリスト
要素リスト = [
'最寄駅:距離(分)', 'レジャー施設', '密度(道路)',...
路:幅員(m)', '居住年数5年未満の人口割合',
'小学校', '一戸建て割合', 'min_distance_to_crime', '...
ン割合', 'ホテル',
'建物の面積比率', 'デパート', '平均次数(道路)', '中...
園',
'最寄り駅名_富山', '最終学歴が大学以上の人口割合', '...
住年数が20年以上の人口割合', '建物の構造_木造',
'高校', '用途_住宅', '延床面積(㎡)', '前面道路:方...
路)',
'都市計画_市街化調整区域'
]
# 不要な列を削除
df.drop(columns=要素リスト, inplace=True)
# 住所をキーにして緯度・経度をマージ
df = df.merge(location_df, on="住所", how="left")
# 取引価格と緯度・経度を削除
df.drop(columns=['取引価格(㎡単価)', '緯度', '経度'...
# CSVの列順を指定(1列目: 住所, 残りの変数)
columns_order = ['住所'] + [col for col in df.columns...
# 指定した列順で保存
df = df[columns_order]
df.to_csv(output_file, index=False, encoding='utf-8-s...
print("データのまとめが完了し、CSVファイルに保存しま...
上の数式を再現したpythonコードが下になります。~
&br;
import os
import pandas as pd
import numpy as np
# ======== CSVファイルの読み込み ========
df_selected_features = pd.read_csv("C:/Users/tn011/De...
与率/選ばれた変数_削除.csv")
df_toyama_data = pd.read_csv("C:/Users/tn011/Desktop/...
まとめたデータ_削除.csv")
# ======== selected_features.csv から 回帰係数と交互...
========
beta_values = df_selected_features.set_index('Feature...
['Coefficient'].to_dict()
# 交互作用項の係数を取得(交互作用項に '×' が含まれる)
interaction_coeffs = {key: value for key, value in be...
'×' in key}
# 交互作用項を除外した beta_values の作成
beta_values_without_interaction = {key: value for key...
beta_values.items() if '×' not in key}
# ======== 寄与率の計算関数 ========
def compute_contribution(x_values, beta_values_withou...
interaction_coeffs, target_var):
beta_0 = 0 # 切片は 0 で固定
delta_x = 1 # 対象変数を 1 増加
# 1. 基準の予測値 log(y) の計算
log_y = beta_0
log_y += sum(beta_values_without_interaction[var] * x...
beta_values_without_interaction if var in x_values)
log_y += sum(interaction_coeffs[interaction] * x_valu...
interaction in interaction_coeffs if interaction in x...
# 2. 対象変数を 1 増加させた場合の log(y')
x_values_new = x_values.copy()
x_values_new[target_var] += delta_x
log_y_new = beta_0
log_y_new += sum(beta_values_without_interaction[var]...
for var in beta_values_without_interaction if var in ...
log_y_new += sum(interaction_coeffs[interaction] * x_...
for interaction in interaction_coeffs if interaction ...
# 3. 寄与率の計算
y_original = np.exp(log_y)
y_new = np.exp(log_y_new)
contribution_rate = ((y_new - y_original) / y_origina...
return contribution_rate
# ======== すべての住所に対する寄与率計算 ========
output_folder = "C:/Users/tn011/Desktop/統計正しいほ...
率"
os.makedirs(output_folder, exist_ok=True)
# すべての住所を取得
target_addresses = df_toyama_data['住所'].unique()
# 各住所に対する寄与率を計算
for target_address in target_addresses:
# 住所ごとのデータをフィルタリング
target_data = df_toyama_data[df_toyama_data['住所'] =...
# 数値カラムのみを抽出して平均を計算
target_data_numeric = target_data.select_dtypes(inclu...
# 住所ごとのデータを取得
x_values = target_data_numeric.to_dict()
# 寄与率を計算する対象の変数を取得
target_vars = list(x_values.keys())
# 各住所の変数ごとの寄与率を計算
contributions = {var: compute_contribution(x_values,
beta_values_without_interaction, interaction_coeffs, ...
target_vars}
# 結果をデータフレームにまとめる
result_df = pd.DataFrame([{'住所': target_address, **...
# CSVファイルとして保存
result_file_path = os.path.join(output_folder, f"{tar...
result_df.to_csv(result_file_path, index=False, encod...
print(f"{target_address} の寄与率が保存されました: {r...
~
「''町ごとの寄与率''」フォルダーにそれぞれの町の寄与率のc...
#ref(kiyo.png,,30%)
#ref(kiyor.png,,50%)
*寄与率のGISによる可視化 [#v6998bc5]
ドライブにあるWeb-GISフォルダを統計正しいほうのフォルダに...
#ref(Web-GIS.png,,30%)
おわり
終了行:
[[技術資料]]
*目次 [#f3c34276]
#CONTENTS
*本研究の目的 [#cec342b3]
本研究の目的は,ヘドニック・アプローチにおける限界を克服...
正確で信頼性の高い評価手法を提供することである.ヘドニッ...
欠落変数のバイアス,交互作用効果および非線形効果の取り扱...
は不動産市場や消費財の価格評価において誤差を生じさせる要...
らの問題を解決するために,スパース推定法を活用した新たな...
従来のヘドニックモデルは,そのシンプルな線形構造と主要変...
で強力であったが,現実の市場では非線形な相互作用や高次の...
十分に捉えることができないことが多かった.また,異なる要...
の効果を正確に評価するためには,より複雑なモデルが求めら...
ElasticNetおよびその進化形であるAdaptiveElasticNet(AEN)を...
することを目指す.
ElasticNetはL1およびL2正則化を組み合わせることで,多重共...
と同時に,重要な変数の選択を行う能力を持つ.これにより,...
え,効果的な変数選択を実現できる.また,AENは,従来のElas...
データの特性に応じて正則化パラメータを動的に調整する.こ...
雑なデータ構造に対して非常に効果的であり,非線形性や交互...
できる.これにより,不動産市場や消費財の価格形成における...
え,価格予測の精度を向上させることが可能となる.
さらに,本研究では,従来の線形回帰モデルでは捉えきれなか...
効果をスパース推定法を活用することで反映させることができ...
技術と組み合わせることにより,より精緻な価格形成モデルが...
見過ごされがちな要因を捉えることが可能となる.例えば,不...
積の相互作用,消費財におけるブランド力と機能性の複合的影...
係性を反映させることで,より現実的な市場分析が行えるよう...
また,こうした高度な統計手法や機械学習技術の活用により,...
ローチを大きく強化することができる.特に,従来のアプロー...
格形成における微細な要因を,スパース推定を用いることで明...
評価を可能にする.これにより,不動産市場や消費財市場にお...
理解が深まり,実務的な応用に貢献することが期待される.
*使用するファイル [#pe64d1b6]
本研究で使用するファイルはすべてGoogleDriveにある。
&br;
user:iie.lab.tpu.2324@gmail.com
&br;
「マイドライブ」→「学生」→「24_o3中島」→「保存期間5年」→...
&br;
「引継ぎ用.zip」をダウンロードする。
&br;
ファイルの中身は以下のようになっている。
これを上から順に実行していく過程を以下の章に示す。
|フォルダ名|用途|ファイル名|ファイルの場所|
|データセットの作成|取引データの緯度経度変換(新しくデータ...
|データセットの作成|犯罪データの取得|get_crime_data.py|デ...
|データセットの作成|統計データなどの作成|hop_統計.ipynb|...
|データセットの作成|取引データのメッシュ変換|緯度経度.py|...
|データセットの作成|各データを取引データにまとめる|hop_メ...
|データセットの作成|犯罪場所との最短距離|distance.ipynb|...
|前処理|データセットの前処理|前処理.ipynb|前処理\前処理.i...
|変数選択|変数の選択とハイパーパラメータのチューニング|変...
|要因分析|選択された変数を用いたヘドニック・アプローチに...
|寄与率|選択された変数の価格に対する寄与率の算出|寄与率.i...
~
それぞれのコードを動かす際に初めに必要なファイル
前処理.ipynbを実行する前にデータセットの作成で作成された...
~
次に変数選択_削除.ipynbを実行する前に前処理で作成された削...
~
hedo_削除.ipynbを実行する前に削除_変数作成後.csvと選ばれ...
~
最後に寄与率.ipynbを実行する前に位置情報_削除.csv、削除_...
~
コードの変更点はディレクトリを変更するだけで大丈夫.
pythonのバージョンは12.0.0を用いる.
使用したモジュールのバージョンは下になります。(すべては...
#ref(module.png,,70%)
** 犯罪発生データの取得 [#k37ae06a]
「''get_crime_data.py''」を実行すると、富山県警が公開して...
&br;
**建築年数の算出 [#i8ed6a27]
建築年の年号を西暦にするために以下の式を書いた列を挿入す...
&br;
=IF(LEFT(M2,2)="令和", 2018 + MID(M2,3,LEN(M2)-3),
IF(LEFT(M2,2)="平成", 1988 + MID(M2,3,LEN(M2)-3),
IF(LEFT(M2,2)="昭和", 1925 + MID(M2,3,LEN(M2)-3), "エ...
次に取引時点から西暦を抜き出す。
&br;
=LEFT(W2,4)
そして、取引時点の西暦から建築年の西暦を引くことで建築年...
最後に残す列は建築年数のみ。~
**使用するデータ [#w637e5db]
実際の取引データはhttps://www.reinfolib.mlit.go.jp/realEs...
データセットの作成\data\estats_mesh、データセットの作成\d...
~
(https://www.e-stat.go.jp/gis/statmap-search?page=1&type=...
~
(https://www.e-stat.go.jp/gis/statmap-search?page=1&type=...
この二つのurlからメッシュごとのデータ。~
(https://www.e-stat.go.jp/stat-search/files?page=1&layout...
このurlから小地域ごとのデータを。~
** データの作成と収集(統計データや施設データ)[#x2b1cdcf]
「''hop_統計.ipynb''」を実行すると、取引データのメッシュ...
NAVITIMEからのスクレイピングや地図画像からのデータ作成を...
&br;
df_torihiki = pd.read_csv(
HERE / "df_housing_toyamacityメッシュ入り.csv",
index_col = "住所",
encoding = 'cp932')
メッシュコードを文字列として格納
&br;
meshes = df_torihiki["mesh_code"].astype(str).tolist()
作成する統計データは以下のようになる。
#ref(作成する統計データ.png,,)
&br;
import pandas as pd
# ここで上で指定した説明変数を生成
df_estats_block = pd.read_csv(
DATA_DIR / "estats_block.csv",
index_col = "KEY_CODE")
df_estats_mesh = pd.read_csv(
DATA_DIR / "estats_mesh.csv",
index_col = "KEY_CODE")
df_selected_block = pd.DataFrame()
df_selected_mesh = pd.DataFrame()
for line in stats_data_text.splitlines():
formula, label = line.rsplit(", ", 2)
if len( formula.split(" ") ) == 1:
if formula in df_estats_block.columns:
df_selected_block.loc[:, label] = df_estats_b...
if formula in df_estats_mesh.columns:
df_selected_mesh.loc[:, label] = df_estats_me...
elif len( formula.split(" ") ) >= 2:
contains_keys = re.findall("T.........", formula)
if contains_keys[0] in df_estats_block.columns:
for key in contains_keys:
formula = formula[:formula.find(key)] + "...
formula[formula.find(key) : formula.f...
"']" + formula[formula.find(key) ...
exec(f"df_selected_block.loc[:, '{label}'] = ...
elif contains_keys[0] in df_estats_mesh.columns: ...
for key in contains_keys:
formula = formula[:formula.find(key)] + "...
formula[formula.find(key) : formu...
"']" + formula[formula.find(k...
exec(f"df_selected_mesh.loc[:, '{label}'] = {...
df_selected_mesh = df_selected_mesh.fillna(0)
df_selected_block = df_selected_block.fillna(0)
df_selected_mesh
df_selected_block
&br;
# 次は施設データ.
# 統計データと同じで,カンマの左側の数字はNAVITIMEの...
# コンビニ一覧のURLは "https://www.navitime.co.jp/cat...
リIDは「0201」
building_data_text = '''\
0201, コンビニ
0802001, 駅
0805, 駐車場
0812, 駐輪場
0501, 金融機関
0603, 旅館
0608, ホテル
0202, スーパー
0205, ショッピングモール
0204, デパート
0502002, 警察署/交番
0504001, 小学校
0504002, 中学校
0504003, 高校
0504004, 大学
0504006, 保育園/幼稚園
0101, レジャー施設'''
# ここで,NAVITIMEからスクレイピング
df_buildings = pd.DataFrame()
def address2coords(address: str):
for trials in range(5):
res = requests.get(
urllib.parse.quote(
string = f"https://msearch.gsi.go.jp/addr...
safe = "://?="
)
)
if res.status_code == 200:
break
else:
time.sleep(5 * trials)
else:
raise Exception("国土地理院のジオコーディングAPI...
result = res.json()
time.sleep(0.5)
# サーバに負担をかけないように0.5秒待つ
if len(result) == 0:
return None
else:
return result[0]["geometry"]["coordinates"]
# 複数ある場合でも,0番目を採用
def get_building_info(category):
df_buildings = pd.DataFrame(columns = ["name", "addre...
for i in range(1, sys.maxsize):
# "while True"と同義
if i == 1:
url = f"https://www.navitime.co.jp/category/{...
else:
url = f"https://www.navitime.co.jp/category/{...
for trials in range(5):
res = requests.get(url)
if res.status_code == 200:
break
else:
time.sleep(5)
else:
break
# NAVITIME から 5 回連続で取得できなかったら...
soup = BeautifulSoup(res.text, "html.parser")
buildings = []
for element in soup.find_all(class_ = "spot-name-...
content = element.get_text()
buildings += [{"name": content}]
count = 0
for element in soup.find_all(class_ = "spot-detai...
content = element.get_text()
matches = re.findall(r"(北海道|東京都|大阪府|...
# 完璧ではないが、これで住所かを判定 ...
if len(matches) > 0:
address = content
coords = address2coords(address)
print(address, coords)
buildings[count]["address"] = address if ...
buildings[count]["lng"] = None
buildings[count]["lat"] = None
else:
buildings[count]["lng"] = coords[0]
buildings[count]["lat"] = coords[1] ...
count += 1
for building in buildings:
df_buildings = add_dict_to_df(building, df_bu...
return df_buildings
集めたデータを用いて不動産の取引が行われた場所の存在する...
**緯度経度からメッシュを格納 [#kea42b7d]
「''緯度経度.py''」を実行すると、地理情報(緯度・経度)か...
&br;
import pandas as pd
def latlon_to_mesh(lat, lon):
"""
緯度経度から9桁のメッシュコード(2分の1地域メッシュ)...
:param lat: 緯度(度)
:param lon: 経度(度)
:return: 9桁のメッシュコード(文字列)
"""
# 1次メッシュ
mesh1_lat = int(lat * 1.5)
mesh1_lon = int(lon - 100)
# 2次メッシュ
mesh2_lat = int((lat * 1.5 - mesh1_lat) * 8)
mesh2_lon = int((lon - 100 - mesh1_lon) * 8)
# 3次メッシュ
mesh3_lat = int(((lat * 1.5 - mesh1_lat) * 8 - mesh2_...
mesh3_lon = int(((lon - 100 - mesh1_lon) * 8 - mesh2_...
# 4次メッシュ(2分の1地域メッシュ)
mesh4_lat = int((((lat * 1.5 - mesh1_lat) * 8 - mesh2...
mesh4_lon = int((((lon - 100 - mesh1_lon) * 8 - mesh2...
# メッシュコードの組み立て(9桁になるよう修正)
mesh_code = f"{mesh1_lat:01}{mesh1_lon:01}{mesh2_lat:...
# 最後の2桁のみ取り出して、9桁にする
mesh_code = mesh_code[:9]
return mesh_code
# CSVファイルの読み込み
file_path = r"C:\Users
t011\Desktop\研究\富山取引のほう富山市のみ
\df_housing_toyamacity.csv"
df = pd.read_csv(file_path, encoding='utf-8')
# メッシュコードの計算
df["mesh_code"] = df.apply(lambda row: latlon_to_mesh...
cols = ["mesh_code"] + [col for col in df.columns if ...
df = df[cols]
# 結果のCSVを保存
output_path = r"C:\Users
t011\Desktop\研究\富山取引のほう富山市のみ
\df_housing_toyamacityメッシュ入り.csv"
df.to_csv(output_path, index=False)
print(f"処理完了: {output_path}")
#ref(作成されるデータ.png,,)
「''hop_メッシュ.ipynb''」を実行すると、メッシュコードご...
# メッシュGeoJsonを,分かりやすい形に直す
_meshes = {}
for mesh in meshes:
meshcode = mesh["properties"]["code"]
coords = mesh["geometry"]["coordinates"][0]
north = coords[1][1]
south = coords[0][1]
east = coords[2][0]
west = coords[0][0]
center = [(east + west) / 2, (north + south) / 2]
_meshes[meshcode] = {
"north": north,
"south": south,
"east": east,
"west": west,
"center": center
}
meshes = _meshes
# 犯罪データの座標から,どのグリッドセルに含まれるか...
# 「mesh_code」列に格納する
# 読み込んだメッシュGeoJsonに含まれない犯罪データは除外
df_temp = df_crimes[0:0].copy()
df_temp["mesh_code"] = None
for index, row in df_crimes.iterrows():
for meshcode, coords in meshes.items():
if ((coords["south"] <= row["latitude"] < coords[...
(coords["west"] <= row["longitude"] < coords[...
if not pd.isnull(row["datetime"]):
df_temp.loc[index] = pd.concat([
row,
pd.Series({
"mesh_code": meshcode
})
])
break
print(f"{df_crimes.index.get_loc(index)} / {len(df_cr...
df_crimes = df_temp.copy()
df_crimes["datetime"] = pd.to_datetime(df_crimes["dat...
# CSVファイルの読み込み
df_crimes = pd.read_csv(HERE / "犯罪_メッシュ入り.csv")
#メッシュごとに件数をカウント
mesh_counts = df_crimes['mesh_code'].value_counts().r...
mesh_counts.columns = ['mesh_code', '件数']
# 結果を表示
print(mesh_counts)
# 結果をCSVファイルに保存する場合
mesh_counts.to_csv(HERE / "犯罪_メッシュ件数.csv", in...
&br;
# 件数データ
df_number = pd.read_csv(
HERE / "犯罪_メッシュ件数.csv",
index_col = "mesh_code")
&br;
# 取引データ
df_torihiki = pd.read_csv(
HERE / "df_housing_toyamacityメッシュ入り.csv",
index_col = "mesh_code",
encoding = 'cp932')
&br;
# メッシュコードをキーとして結合
df_merged = pd.merge(df_torihiki, df_number, on='mesh...
suffixes=('', '_number'))
print(df_merged.head())
# 結果をCSVファイルに保存する場合
df_merged.to_csv(HERE / "取引_件数付き.csv", encoding...
&br;
df_mesh = pd.read_csv(
HERE / "data_by_mesh.csv",
index_col = "mesh_code",
encoding = "cp932")
&br;
df_torihiki2 = pd.read_csv(
HERE / "取引_件数付き.csv",
index_col = "mesh_code")
&br;
# メッシュコードでデータを結合
merged_df = pd.merge(df_torihiki2, df_mesh, on='mesh_...
print(merged_df.head())
merged_df.to_csv(HERE / "取引_統計データ付き.csv", in...
encoding='utf-8-sig')
犯罪発生率(件/250000)はhop_メッシュ.ipynbを行った後にcsv...
計算方法は=件数/250000で行う。~
件数列の空欄は0に統一する。~
取引_統計データ付き.csvに手動でdf_housing_toyamacityメッ...
#ref(統計データ.png,,20%)
「''distance.ipynb''」を実行すると、住宅地データ (取引_統...
import pandas as pd
from geopy.distance import geodesic
# ファイルを読み込む
df_housing = pd.read_csv("C:/Users/nt011/Desktop/統計...
の作成/取引_統計データ付き.csv")
df_crimes = pd.read_csv("C:/Users/nt011/Desktop/統計...
の作成/犯罪_メッシュ入り.csv")
print(df_housing.columns)
# 1. 住宅地データの緯度経度情報を抽出
df_housing['latitude'] = df_housing['緯度']
df_housing['longitude'] = df_housing['経度']
# 2. 犯罪データの緯度経度情報を抽出
df_crimes['latitude'] = df_crimes['latitude']
df_crimes['longitude'] = df_crimes['longitude']
# 3.最短距離を計算する関数
def calculate_min_distance(lat1, lon1, df_target, lat...
distances = df_target.apply(lambda row: geodesic((lat...
(row[lat_col], row[lon_col])).meters, axis=1)
return distances.min()
# 4. 各住宅地から犯罪発生場所までの最短距離を計算
df_housing['min_distance_to_crime'] = df_housing.appl...
calculate_min_distance(row['latitude'], row['longitud...
# 距離が0になる住宅地の行を表示
df_housing[df_housing['min_distance_to_crime'] == 0]
# 必要なカラムを選択して新しいDataFrameに保存
df_result = df_housing[['mesh_code', '住所', '経度', ...
'土地の形状', '間口', '延床面積(...
'用途', '前面道路:方位', '前面道...
'容積率(%)', '取引時点', '件数...
'65歳以上人口割合', '外国人人口割...
'非正規労働者割合', '最終学歴が中...
'居住年数5年未満の人口割合', '居...
'高層マンション割合', 'コンビニ',...
'保育園/幼稚園', 'レジャー施設',...
'ノード数(道路)', 'エッジ数(道...
# 結果の保存
df_result.to_csv('C:/Users/nt011/Desktop/統計正しいほ...
住宅地_犯罪_最短距離.csv', index=False, encoding='utf-8-...
#ref(最短.png,,20%)&br;
&br;
** データセットの前処理 [#u50edad0]
作成したデータセットを回帰分析がかけられる形に整える。
&br;
「''前処理.ipynb''」を実行し、「''住宅地_犯罪_最短距離.cs...
&br;
import pandas as pd
# CSVファイルのパス
file_path = r"C:\Users
t011\Desktop\統計正しいほう\前処理\住宅地_犯罪_最短距...
# CSVファイルを読み込む
df = pd.read_csv(file_path)
# 欠損値を含む行を削除
df = df.dropna()
# 「建築年数」列に `-1` または `"VALUE"` を含む行を削除
df = df[~df["建築年数"].astype(str).isin(["-1", "#VAL...
# 「最寄駅:距離(分)」の値を変換
replace_dict = {
"30分~60分": 45,
"1H~1H30": 75,
"1H30~2H": 105
}
df["最寄駅:距離(分)"] = df["最寄駅:距離(分)"].r...
# クリーンなデータを新しいCSVファイルとして保存
output_path = r"C:\Users
t011\Desktop\統計正しいほう\前処理\住宅地_犯罪_最短距...
df.to_csv(output_path, index=False, encoding='utf-8-s...
print("データ処理完了: 欠損値と指定された異常値を削除...
print(f"新しいCSVファイルが {output_path} に保存され...
生成した「''住宅地_犯罪_最短距離_欠損値削除後.csv''」から...
◆不動産取引価格~
https://www.reinfolib.mlit.go.jp/realEstatePrices/~
~
このurlの制度と用語のページを参考にして変換を行う。
#ref(建物の構造.png,,30%)
&br;
import pandas as pd
# CSVファイルのパス
file_path = "C:/Users/nt011/Desktop/統計正しいほう/前...
離_欠損値削除後.csv"
# CSVファイルを読み込む
df = pd.read_csv(file_path)
# 外れ値を検出する連続変数のカラムリスト
continuous_columns = [
"最寄駅:距離(分)", "取引価格(総額)", "面積(㎡)...
"間口", "延床面積(㎡)", "建築年数", "前面道路:幅員...
"建ぺい率(%)", "容積率(%)", "犯罪発生率(件/2500...
"18歳未満人口割合", "65歳以上人口割合", "外国人人口割...
"単身世帯割合", "核家族世帯割合", "正規労働者割合", "...
"最終学歴が中学以下の人口割合", "最終学歴が高校の人口...
"居住年数5年未満の人口割合", "居住年数が20年以上の人...
"アパート・低中層マンション割合", "高層マンション割合...
"建物の面積比率", "水の面積比率", "空き地の面積比率",...
"エッジ数(道路)", "密度(道路)", "平均次数(道路)...
]
# データ型を数値に変換(エラーが出たらNaNにする)
for column in continuous_columns:
if column in df.columns:
df[column] = pd.to_numeric(df[column], errors='co...
# 外れ値を持つ行のインデックスを格納するリスト
outlier_indices = set()
# 外れ値の検出と削除
for column in continuous_columns:
if column in df.columns:
# 欠損値を除外
df_clean = df[column].dropna()
# IQR(四分位範囲)の計算
Q1 = df_clean.quantile(0.25)
Q3 = df_clean.quantile(0.75)
IQR = Q3 - Q1
# 外れ値の閾値を設定
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 外れ値のインデックスを取得
outliers = df[(df[column] < lower_bound) | (df[co...
outlier_indices.update(outliers.index)
# 外れ値の行を削除
df_cleaned = df.drop(index=outlier_indices)
# 結果を新しいCSVに保存
output_path = "C:/Users/nt011/Desktop/統計正しいほう/...
df_cleaned.to_csv(output_path, encoding="utf-8-sig", ...
print(f"外れ値を削除したデータを {output_path} に保存...
print(f"削除した行数: {len(outlier_indices)}")
print(f"最終データの行数: {df_cleaned.shape[0]}")
それぞれのカラムの要素を必要に応じてダミー変数化した後、...
import pandas as pd
# CSVファイルを読み込み
df_data = pd.read_csv("C:/Users/nt011/Desktop/統計正...
# カラム名を取得
columns = df_data.columns.tolist()
# 建物の構造列に「RC」がある場合、「鉄筋コンクリート...
df_data['建物の構造'] = df_data['建物の構造'].replace...
# 最寄り駅名を二値化(列名を「最寄り駅名_富山」に変更)
index = columns.index("最寄駅:名称") # 変換前の位置...
df_data.insert(index + 1, '最寄り駅名_富山', df_data[...
df_data = df_data.drop(columns=['最寄駅:名称']) # ...
# 都市計画を二値化(列名を「都市計画_市街化調整区域」...
index = columns.index("都市計画")
df_data.insert(index + 1, '都市計画_市街化調整区域', ...
df_data = df_data.drop(columns=['都市計画'])
# 土地の形状を二値化(列名を「土地の形状_不整形」に変...
index = columns.index("土地の形状")
df_data.insert(index + 1, '土地の形状_不整形', df_dat...
df_data = df_data.drop(columns=['土地の形状'])
# 用途を二値化(列名を「用途_住宅」に変更)
index = columns.index("用途")
df_data.insert(index + 1, '用途_住宅', df_data['用途'...
df_data = df_data.drop(columns=['用途'])
# 建物の構造を二値化(列名を「建物の構造_木造」に変更)
index = columns.index("建物の構造")
df_data.insert(index + 1, '建物の構造_木造', df_data[...
df_data = df_data.drop(columns=['建物の構造'])
# 「前面道路:方位」のダミー変数化(基準値「北西」を0...
index = columns.index("前面道路:方位") # 変換前の位...
dummies = pd.get_dummies(df_data['前面道路:方位'], p...
# 基準値は削除
baseline_value = '北西'
if f'前面道路:方位_{baseline_value}' in dummies.colu...
dummies = dummies.drop(columns=[f'前面道路:方位_{bas...
# 挿入(前面道路:方位のダミー変数)
ordered_dummies = ['前面道路:方位_西', '前面道路:方...
'前面道路:方位_南', '前面道路:方位_...
# 順番に従って挿入
for col in ordered_dummies:
if col in dummies.columns:
df_data.insert(index + 1, col, dummies[col])
# 「前面道路:種類」のダミー変数化
road_types = ['市道', '私道', '県道']
# 順番を指定してダミー変数を挿入
for road in road_types:
df_data.insert(index + 1, f'前面道路:種類_{road}', (...
# 元の「前面道路:方位」および「前面道路:種類」列を...
df_data = df_data.drop(columns=['前面道路:方位', '前...
# 確認用にダミー変数化後のデータフレームを表示
print(df_data.head())
# ダミー変数化後のデータを保存
df_data.to_csv("C:/Users/nt011/Desktop/統計正しいほう...
index=False, encoding='utf-8-sig')
print("ダミー変数変換完了!データが保存されました。")
#ref(ダミー.png,,20%)
&br;
連続変数とダミー変数を手動で分類し、連続変数のみ二次項の...
交互作用項の作成したデータフレームを保存した「''削除_変数...
import pandas as pd
import numpy as np
from itertools import combinations
# CSVファイルのパスを指定
file_path = "C:/Users/nt011/Desktop/統計正しいほう/前...
# UTF-8で読み込む
df = pd.read_csv(file_path)
# データの先頭を表示
print(df.head())
# 連続変数とダミー変数を手動で分類
continuous_vars = [
'最寄駅:距離(分)', '面積(㎡)', '間口', '延床面積...
'建ぺい率(%)', '容積率(%)', '犯罪発生率(件/2500...
'65歳以上人口割合', '外国人人口割合', '世帯数', '単身...
'正規労働者割合', '非正規労働者割合', '最終学歴が中学...
'最終学歴が大学以上の人口割合', '居住年数5年未満の人...
'一戸建て割合', 'アパート・低中層マンション割合', 'コ...
'金融機関', '旅館', 'ホテル', 'スーパー', 'ショッピン...
'デパート', '警察署/交番', '小学校', '中学校', '高校...
'レジャー施設','道路の面積比率', '建物の面積比率', '...
'ノード数(道路)', 'エッジ数(道路)', '密度(道路)...
]
# ダミー変数をリストとして定義
dummy_vars = [
'最寄り駅名_富山','土地の形状_不整形', '建物の構造_木...
'用途_住宅', '前面道路:方位_北', '前面道路:方位_北...
'前面道路:方位_南', '前面道路:方位_南東',
'前面道路:方位_南西', '前面道路:方位_東', '前面道路...
'前面道路:種類_市道', '前面道路:種類_県道', '前面道...
'都市計画_市街化調整区域'
]
# 二次項の作成(連続変数のみ)
for var in continuous_vars:
df[f'{var}^2'] = df[var] ** 2
# 交互作用項の作成
# 連続変数 × 連続変数
for var1, var2 in combinations(continuous_vars, 2):
df[f'{var1}×{var2}'] = df[var1] * df[var2]
# ダミー変数 × 連続変数
for dummy_var in dummy_vars:
for cont_var in continuous_vars:
df[f'{dummy_var}×{cont_var}'] = df[dummy_var] * d...
# ダミー変数 × ダミー変数
for var1, var2 in combinations(dummy_vars, 2):
df[f'{var1}×{var2}'] = df[var1] * df[var2]
# CSVに保存
output_path = "C:/Users/nt011/Desktop/統計正しいほう/...
df.to_csv(output_path, index=False, encoding='utf-8-s...
print(f"処理が完了しました。生成されたデータは {outpu...
#ref(交互作用項.png,,20%)
&br;
*変数選択 [#u9327c42]
***Elastic Netとは [#d2ec2870]
Elastic Netは、L1 正則化(Lasso)と L2 正則化(Ridge)の...
Lasso(L1正則化):L1正則化は、回帰モデルの係数の一部をゼ...
&br;
Ridge(L2正則化):L2正則化は、回帰モデルの係数を小さくす...
&br;
StandardScaler() を用いて X(説明変数)と y(目的変数)を...
Adaptive Elastic Netを用いて土地の価格に影響する重要な特...
#ref(式.png,,50%)
***手順 [#d2ec2870]
「''変数選択__削除.ipynb''」を実行すると、重要な変数のみ...
import numbers
import warnings
import cvxpy
import numpy as np
from asgl import ASGL
from sklearn.base import MultiOutputMixin
from sklearn.base import RegressorMixin
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import ElasticNet
from sklearn.linear_model._coordinate_descent import ...
from sklearn.utils import check_X_y
from sklearn.utils.validation import check_is_fitted
class AdaptiveElasticNet(ASGL, ElasticNet, MultiOutpu...
"""
Objective function and parameters as described with m...
to allow alpha1, alpha2, l1_ratio1, and l1_ratio2 cus...
"""
def __init__(
self,
alpha1=0.021544346900318846, # First-stage Elas...
alpha2=0.0009443498043343188, # Second-stage Ela...
*,
l1_ratio1=0.8889, # First-stage ElasticNet L1 ra...
l1_ratio2=0.778, # Second-stage ElasticNet L1 ra...
gamma=0.5, # Weight adjustment exponent
fit_intercept=True,
precompute=False,
max_iter=10000,
copy_X=True,
solver=None,
tol=None,
positive=False,
positive_tol=1e-3,
random_state=None,
eps_coef=1e-6,
verbose=True
):
params_asgl = dict(model="lm", penalization="asgl")
if solver is not None:
params_asgl["solver"] = solver
if tol is not None:
params_asgl["tol"] = tol
super().__init__(**params_asgl)
self.alpha1 = alpha1
self.alpha2 = alpha2
self.l1_ratio1 = l1_ratio1
self.l1_ratio2 = l1_ratio2
self.gamma = gamma
self.fit_intercept = fit_intercept
self.max_iter = max_iter
self.precompute = precompute
self.copy_X = copy_X
self.positive = positive
self.positive_tol = positive_tol
self.random_state = random_state
self.eps_coef = eps_coef
self.verbose = verbose
if not self.fit_intercept:
raise NotImplementedError
def fit(self, X, y, check_input=True):
if check_input:
X_copied = self.copy_X and self.fit_intercept
X, y = self._validate_data(
X,
y,
accept_sparse="csc",
order="F",
dtype=[np.float64, np.float32],
copy=X_copied,
multi_output=True,
y_numeric=True,
)
# 第一段階の ElasticNet 実行
enet_model_1 = self.elastic_net(self.l1_ratio1, a...
enet_model_1.fit(X, y)
enet_coef = enet_model_1.coef_
# 重みの計算
weights = 1.0 / (np.maximum(np.abs(enet_coef), se...
# 第二段階の最適化
self.coef_, self.intercept_ = self._optimize_seco...
# モデル属性を格納
self.enet_coef_ = enet_coef
self.weights_ = weights
return self
def predict(self, X):
check_is_fitted(self, ["coef_", "intercept_"])
return super(ElasticNet, self).predict(X)
def elastic_net(self, l1_ratio, **params):
"""
Create an ElasticNet model with the specified par...
"""
elastic_net = ElasticNet(l1_ratio=l1_ratio)
for k, v in self.get_params().items():
try:
elastic_net = elastic_net.set_params(**{k...
except ValueError:
pass # Ignore parameters not supported b...
elastic_net = elastic_net.set_params(**params)
return elastic_net
def _optimize_second_stage(self, X, y, weights):
"""
Perform second-stage optimization with adaptive w...
Returns
-------
coef : np.array, shape (n_features,)
intercept : float
"""
n_samples, n_features = X.shape
beta_variables = [cvxpy.Variable(n_features)]
model_prediction = 0.0
if self.fit_intercept:
beta_variables = [cvxpy.Variable(1)] + beta_v...
ones = cvxpy.Constant(np.ones((n_samples, 1)))
model_prediction += ones @ beta_variables[0]
# モデル予測
model_prediction += X @ beta_variables[1]
error = cvxpy.sum_squares(y - model_prediction) /...
l1_coefs = self.alpha2 * self.l1_ratio2
# 第二段階の正則化項
l1_penalty = cvxpy.Constant(l1_coefs * weights) @...
beta_variables[1]
)
l2_penalty = (
cvxpy.Constant(self.alpha1 * (1 - self.l1_rat...
* cvxpy.sum_squares(beta_variables[1])
)
constraints = [b >= 0 for b in beta_variables] if...
# 最適化問題の定義
problem = cvxpy.Problem(
cvxpy.Minimize(error + l1_penalty + l2_penalt...
constraints=constraints
)
problem.solve(solver="OSQP", max_iter=self.max_it...
if problem.status != "optimal":
raise ConvergenceWarning(
f"Solver did not reach optimum (Status: {...
)
beta_sol = np.concatenate([b.value for b in beta_...
beta_sol[np.abs(beta_sol) < self.tol] = 0
intercept, coef = beta_sol[0], beta_sol[1:]
coef = np.maximum(coef, 0) if self.positive else ...
return coef, intercept
from sklearn.linear_model import ElasticNetCV
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import make_regression
import numpy as np
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.preprocessing import StandardScaler
# CSVファイルのパスを指定してください
file_path = "C:/Users/nt011/Desktop/統計正しいほう/変...
# CSVファイルの読み込み
df = pd.read_csv(file_path) # 文字コードが異なる場合...
# 特徴量とターゲットの分割
X = df.drop(columns=['取引価格(㎡単価)']) # 取引価...
y = df['取引価格(㎡単価)'] # ターゲット変数
# 🔥 標準化の実施
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X) # Xの標準化
y_scaled = scaler_y.fit_transform(y.values.reshape(-1...
# データ分割
X_train, X_test, y_train, y_test = train_test_split(X...
test_size=0.2, random_state=42)
# 訓練データの一部を使用
X_sample, _, y_sample, _ = train_test_split(X_train, ...
random_state=42)
# 第一段階: ElasticNetCVを使用した最適パラメータの導出
enet_cv = ElasticNetCV(
l1_ratio=np.linspace(0.0001, 1, 25), # l1_ratioの候補
alphas=np.logspace(-5, 0, 25), # alphaの候補
cv=5, # 交差検証の分割数
random_state=42,
n_jobs=-1,
verbose=1
)
enet_cv.fit(X_train, y_train)
# 第一段階の最適パラメータと係数を取得
alpha1_opt = enet_cv.alpha_
l1_ratio1_opt = enet_cv.l1_ratio_
enet_coef = enet_cv.coef_
print(f"第一段階の最適パラメータ: alpha1={alpha1_opt}...
{l1_ratio1_opt}")
# ベストパラメータをalpha2とl1_ratio2でそれぞれ格納
best_alpha2 = best_params['alpha2']
best_l1_ratio2 = best_params['l1_ratio2']
print(best_alpha2)
print(best_l1_ratio2)
ASGLとElasticNetを組み合わせたAdaptiveElasticNetクラスを...
import numbers
import warnings
import cvxpy
import numpy as np
from asgl import ASGL
from sklearn.base import MultiOutputMixin
from sklearn.base import RegressorMixin
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import ElasticNet
from sklearn.linear_model._coordinate_descent import ...
from sklearn.utils import check_X_y
from sklearn.utils.validation import check_is_fitted
class AdaptiveElasticNet(ASGL, ElasticNet, MultiOutpu...
"""
Objective function and parameters as described with m...
to allow alpha1, alpha2, l1_ratio1, and l1_ratio2 cus...
"""
def __init__(
self,
alpha1=0.01333521432163324, # 第一段階で得られ...
alpha2=0.034807005884284134, # Second-stage Elas...
*,
l1_ratio1=1, # First-stage ElasticNet L1 ratio
l1_ratio2=0.1667499999999998, # Second-stage Ela...
gamma=0.5, # Weight adjustment exponent
fit_intercept=True,
precompute=False,
max_iter=10000,
copy_X=True,
solver=None,
tol=None,
positive=False,
positive_tol=1e-3,
random_state=None,
eps_coef=1e-6,
verbose=True
):
params_asgl = dict(model="lm", penalization="asgl")
if solver is not None:
params_asgl["solver"] = solver
if tol is not None:
params_asgl["tol"] = tol
super().__init__(**params_asgl)
self.alpha1 = alpha1
self.alpha2 = alpha2
self.l1_ratio1 = l1_ratio1
self.l1_ratio2 = l1_ratio2
self.gamma = gamma
self.fit_intercept = fit_intercept
self.max_iter = max_iter
self.precompute = precompute
self.copy_X = copy_X
self.positive = positive
self.positive_tol = positive_tol
self.random_state = random_state
self.eps_coef = eps_coef
self.verbose = verbose
if not self.fit_intercept:
raise NotImplementedError
def fit(self, X, y, check_input=True):
if check_input:
X_copied = self.copy_X and self.fit_intercept
X, y = self._validate_data(
X,
y,
accept_sparse="csc",
order="F",
dtype=[np.float64, np.float32],
copy=X_copied,
multi_output=True,
y_numeric=True,
)
# 第一段階の ElasticNet 実行
enet_model_1 = self.elastic_net(self.l1_ratio1, a...
enet_model_1.fit(X, y)
enet_coef = enet_model_1.coef_
# 重みの計算
weights = 1.0 / (np.maximum(np.abs(enet_coef), se...
# 第二段階の最適化
self.coef_, self.intercept_ = self._optimize_seco...
# モデル属性を格納
self.enet_coef_ = enet_coef
self.weights_ = weights
return self
def predict(self, X):
check_is_fitted(self, ["coef_", "intercept_"])
return super(ElasticNet, self).predict(X)
def elastic_net(self, l1_ratio, **params):
"""
Create an ElasticNet model with the specified par...
"""
elastic_net = ElasticNet(l1_ratio=l1_ratio)
for k, v in self.get_params().items():
try:
elastic_net = elastic_net.set_params(**{k...
except ValueError:
pass # Ignore parameters not supported b...
elastic_net = elastic_net.set_params(**params)
return elastic_net
def _optimize_second_stage(self, X, y, weights):
"""
Perform second-stage optimization with adaptive w...
Returns
-------
coef : np.array, shape (n_features,)
intercept : float
"""
n_samples, n_features = X.shape
beta_variables = [cvxpy.Variable(n_features)]
model_prediction = 0.0
if self.fit_intercept:
beta_variables = [cvxpy.Variable(1)] + beta_v...
ones = cvxpy.Constant(np.ones((n_samples, 1)))
model_prediction += ones @ beta_variables[0]
# モデル予測
model_prediction += X @ beta_variables[1]
error = cvxpy.sum_squares(y - model_prediction) /...
l1_coefs = self.alpha2 * self.l1_ratio2
# 第二段階の正則化項
l1_penalty = cvxpy.Constant(l1_coefs * weights) @...
beta_variables[1]
)
l2_penalty = (
cvxpy.Constant(self.alpha1 * (1 - self.l1_rat...
* cvxpy.sum_squares(beta_variables[1])
)
constraints = [b >= 0 for b in beta_variables] if...
# 最適化問題の定義
problem = cvxpy.Problem(
cvxpy.Minimize(error + l1_penalty + l2_penalt...
constraints=constraints
)
problem.solve(solver="OSQP", max_iter=self.max_it...
if problem.status != "optimal":
raise ConvergenceWarning(
f"Solver did not reach optimum (Status: {...
)
beta_sol = np.concatenate([b.value for b in beta_...
beta_sol[np.abs(beta_sol) < self.tol] = 0
intercept, coef = beta_sol[0], beta_sol[1:]
coef = np.maximum(coef, 0) if self.positive else ...
return coef, intercept
import pandas as pd
from sklearn.preprocessing import StandardScaler
# CSVファイルのパスを指定してください
file_path = "C:/Users/monda/OneDrive/デスクトップ/統...
削除_変数作成後.csv"
# CSVファイルの読み込み
df = pd.read_csv(file_path) # 文字コードが異なる場合...
コーディングに変更してください
# 特徴量とターゲットの分割
X = df.drop(columns=['取引価格(㎡単価)']) # 取引価...
離
y = df['取引価格(㎡単価)'] # ターゲット変数
# 🔥 標準化の実施
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X) # Xの標準化
y_scaled = scaler_y.fit_transform(y.values.reshape(-1...
準化
model = AdaptiveElasticNet()
model.fit(X_scaled, y_scaled)
# 係数の表示(重要な特徴量を確認)
coef = model.coef_
print("特徴量の係数:", coef)
# 係数がゼロでない特徴量を選定
selected_features = X.columns[coef != 0]
print("選定された特徴量:", selected_features)
# 係数と特徴量名をデータフレームに変換
selected_features_df = pd.DataFrame({
'Feature': X.columns,
'Coefficient': coef
})
# 係数がゼロでない特徴量のみをフィルタリング
selected_features_df = selected_features_df[selected_...
# CSVファイルとして保存
output_file_path = "選ばれた変数.csv" # 保存先を指定...
selected_features_df.to_csv(output_file_path, index=F...
# 日本語対応のエンコーディング
print(f"選定された特徴量と係数を {output_file_path} ...
#ref(変数選択.png,,50%)
&br;
AENの数式は以下のようなものを扱う。そして、今回行ったハイ...
AENの推計は,二段階で行われる.まず,予備推計としてEN で...
うえで,係数の絶対値が小さい変数に対してより強い罰則を与...
項を変数ごとに調整したうえで,改めてEN を実施する.
#ref(AEN.png,,150%)
#ref(ハイパーパラメータ.png,,150%)
選択された変数は以下のようになる
#ref(選ばれた変数.png,,)
*要因分析 [#w249dca6]
***手順 [#d20580fd]
「''hedo.ipynb''」を実行すると、有意水準に基づいて有意性...
import pandas as pd
# Excelファイルを読み込み
file_path = "c:/Users/nt011/Desktop/統計正しいほう/要...
除.csv"
df = pd.read_csv(file_path)
# 住所が含まれている列を特定して、住所ごとの出現回数...
address_column = '住所' # 住所列の名前がわからない場...
さい
if address_column in df.columns:
address_counts = df[address_column].dropna().value_co...
現回数を集計
# 出現回数をデータフレームに変換
address_counts_df = address_counts.reset_index()
address_counts_df.columns = ['住所', '出現回数'] # ...
# 結果をCSVファイルに書き出し
output_file = "c:/Users/nt011/Desktop/統計正しいほう/...
削除.csv"
address_counts_df.to_csv(output_file, index=False, en...
# UTF-8エンコーディングで保存
print(f"住所ごとの出現回数がCSVファイルに保存されまし...
else:
print("住所列が見つかりません")
回帰係数、t値、p値、有意性を格納したリストを「''回帰分析...
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
# ファイルパスの指定
selected_features_path = "選ばれた変数_削除.csv"
all_data_path = "c:/Users/nt011/Desktop/統計正しいほ...
成後.csv"
location_data_path = "c:/Users/nt011/Desktop/統計正し...
報_削除.csv"
output_data_path = "選択された特徴量とデータ_削除.csv"
# 選定された変数のCSVファイルを読み込み
selected_features_df = pd.read_csv(selected_features_...
selected_features = selected_features_df['Feature'].t...
# 元データを再度読み込み
all_data_df = pd.read_csv(all_data_path)
# 選定された説明変数と目的変数を抽出
df = all_data_df[selected_features + ['取引価格(㎡単...
# 位置情報データを読み込み
location_df = pd.read_csv(location_data_path, usecols...
# 元データと位置情報を結合(共通のキーがある場合)
df = pd.concat([df, location_df], axis=1)
# 統合データをCSVファイルとして保存
df.to_csv(output_data_path, index=False, encoding='ut...
print(f"選定された変数と位置情報を含むデータを {outpu...
した。")
import pandas as pd
# ファイルパス
count_file = "c:/Users/nt011/Desktop/統計正しいほう/...
data_file = "C:/Users/nt011/Desktop/統計正しいほう/要...
output_file = "C:/Users/nt011/Desktop/統計正しいほう/...
# CSVファイルの読み込み
count_df = pd.read_csv(count_file, encoding='utf-8-si...
data_df = pd.read_csv(data_file, encoding='utf-8-sig')
# 住所列の名前
address_column = '住所'
# 緯度・経度を除外(該当カラムがある場合)
drop_columns = ['緯度', '経度']
data_df = data_df.drop(columns=[col for col in drop_c...
data_df.columns])
# 住所の出現回数をデータに統合
merged_df = data_df.merge(count_df, on=address_column...
# 出現回数の多い順にソート
sorted_df = merged_df.sort_values(by='出現回数', asce...
# ソート済みデータをCSVに保存
sorted_df.to_csv(output_file, encoding='utf-8-sig', i...
print(f"ソート済みデータを {output_file} に保存しまし...
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
import statsmodels.api as sm
# データの読み込み
file_path = "C:/Users/nt011/Desktop/統計正しいほう/要...
data = pd.read_csv(file_path)
# 目的変数と説明変数の設定
y = data['取引価格(㎡単価)'] # 取引価格を目的変数に
X = data.drop(columns=['取引価格(㎡単価)', '住所'])...
# 🔥 標準化の実施
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X) # Xの標準化
y_scaled = scaler_y.fit_transform(y.values.reshape(-1...
準化
# 線形回帰モデルの作成
model = LinearRegression()
model.fit(X_scaled, y)
# 回帰分析の結果を表示
X_scaled_with_const = sm.add_constant(X_scaled) # 定...
ols_model = sm.OLS(y, X_scaled_with_const).fit()
# 必要な情報を抽出
r_squared = ols_model.rsquared # 決定係数
coefficients = ols_model.params # 回帰係数(定数項も...
t_values = ols_model.tvalues # t値(定数項も含む)
p_values = ols_model.pvalues # p値(有意水準を判定す...
variable_names = ['定数項'] + list(X.columns)
# 有意水準に基づいて有意性を判定する関数
def significance(p_value):
if p_value < 0.01:
return "1% 有意"
elif p_value < 0.05:
return "5% 有意"
elif p_value < 0.10:
return "10% 有意"
else:
return "有意でない"
# 結果を格納するリスト
results = []
# 回帰係数、t値、p値、有意性をリストに格納
for var_name, coef, t_val, p_val in zip(variable_name...
t_values, p_values):
significance_level = significance(p_val)
results.append([var_name, coef, t_val, p_val, signifi...
# 結果をDataFrameに変換
results_df = pd.DataFrame(results, columns=["変数", "...
値", "有意性"])
# 予測値の計算
data["標準化予測取引価格(㎡単価)"] =
ols_model.predict(X_scaled_with_const)
data["標準化実測取引価格(㎡単価)"] = y_scaled
# **結果を表示**
print("
==== 回帰分析結果 ====")
print(f"決定係数 (R^2): {r_squared:.4f}
")
print(results_df)
# 予測結果を含めたデータを保存
predicted_output_file_path = "C:/Users/nt011/Desktop/...
析/予測結果_削除.csv"
data.to_csv(predicted_output_file_path, index=False, ...
# CSVファイルとして保存
output_file_path = "C:/Users/nt011/Desktop/統計正しい...
結果_削除.csv"
results_df.to_csv(output_file_path, index=False, enco...
print(f"回帰分析結果が{output_file_path}に保存されま...
#ref(ヘドニック.png,,50%)
*寄与率の算出 [#u04f9941]
寄与率は下の数式と変数で算出を行う。~
実行を行う前に寄与率フォルダ内に町ごとの寄与率フォルダを...
寄与率.ipynbを上から実行する。~
#ref(寄与率_数式.png,,)
#ref(寄与率_変数.png,,)
AENで選ばれた一次項、二次項、交互作用項から一次項、二次項...
選ばれた変数によって交互作用項の計算と不要な変数の削除の...
具体的には面積(㎡)×建ぺい率(%)が選ばれた場合には、交...
&br;
import pandas as pd
import os
# データの読み込み
data_file = "C:/Users/tn011/Desktop/統計正しいほう/寄...
除.csv"
location_file = "C:/Users/tn011/Desktop/統計正しいほ...
度経度_削除.csv"
output_file = "C:/Users/tn011/Desktop/統計正しいほう/...
削除.csv"
df = pd.read_csv(data_file)
location_df = pd.read_csv(location_file)
# 交互作用項の計算
交互作用項 = [
('最寄駅:距離(分)', 'レジャー施設'),
('最寄駅:距離(分)', '密度(道路)'),
('面積(㎡)', '前面道路:幅員(m)'),
('居住年数5年未満の人口割合', '小学校'),
('一戸建て割合', 'min_distance_to_crime'),
('アパート・低中層マンション割合', 'min_distance_to_c...
('ホテル', '建物の面積比率'),
('デパート', '平均次数(道路)'),
('中学校', '建物の面積比率'),
('保育園/幼稚園', 'min_distance_to_crime'),
('最寄り駅名_富山', '最終学歴が大学以上の人口割合'),
('土地の形状_不整形', '居住年数が20年以上の人口割合'),
('建物の構造_木造', '面積(㎡)'),
('建物の構造_木造', '高校'),
('用途_住宅', '延床面積(㎡)'),
('前面道路:方位_南東', 'エッジ数(道路)'),
('都市計画_市街化調整区域', '中学校'),
]
# 交互作用項を計算し、列を追加
for var1, var2 in 交互作用項:
df[f'{var1}×{var2}'] = df[var1] * df[var2]
# 不要な要素のリスト
要素リスト = [
'最寄駅:距離(分)', 'レジャー施設', '密度(道路)',...
路:幅員(m)', '居住年数5年未満の人口割合',
'小学校', '一戸建て割合', 'min_distance_to_crime', '...
ン割合', 'ホテル',
'建物の面積比率', 'デパート', '平均次数(道路)', '中...
園',
'最寄り駅名_富山', '最終学歴が大学以上の人口割合', '...
住年数が20年以上の人口割合', '建物の構造_木造',
'高校', '用途_住宅', '延床面積(㎡)', '前面道路:方...
路)',
'都市計画_市街化調整区域'
]
# 不要な列を削除
df.drop(columns=要素リスト, inplace=True)
# 住所をキーにして緯度・経度をマージ
df = df.merge(location_df, on="住所", how="left")
# 取引価格と緯度・経度を削除
df.drop(columns=['取引価格(㎡単価)', '緯度', '経度'...
# CSVの列順を指定(1列目: 住所, 残りの変数)
columns_order = ['住所'] + [col for col in df.columns...
# 指定した列順で保存
df = df[columns_order]
df.to_csv(output_file, index=False, encoding='utf-8-s...
print("データのまとめが完了し、CSVファイルに保存しま...
上の数式を再現したpythonコードが下になります。~
&br;
import os
import pandas as pd
import numpy as np
# ======== CSVファイルの読み込み ========
df_selected_features = pd.read_csv("C:/Users/tn011/De...
与率/選ばれた変数_削除.csv")
df_toyama_data = pd.read_csv("C:/Users/tn011/Desktop/...
まとめたデータ_削除.csv")
# ======== selected_features.csv から 回帰係数と交互...
========
beta_values = df_selected_features.set_index('Feature...
['Coefficient'].to_dict()
# 交互作用項の係数を取得(交互作用項に '×' が含まれる)
interaction_coeffs = {key: value for key, value in be...
'×' in key}
# 交互作用項を除外した beta_values の作成
beta_values_without_interaction = {key: value for key...
beta_values.items() if '×' not in key}
# ======== 寄与率の計算関数 ========
def compute_contribution(x_values, beta_values_withou...
interaction_coeffs, target_var):
beta_0 = 0 # 切片は 0 で固定
delta_x = 1 # 対象変数を 1 増加
# 1. 基準の予測値 log(y) の計算
log_y = beta_0
log_y += sum(beta_values_without_interaction[var] * x...
beta_values_without_interaction if var in x_values)
log_y += sum(interaction_coeffs[interaction] * x_valu...
interaction in interaction_coeffs if interaction in x...
# 2. 対象変数を 1 増加させた場合の log(y')
x_values_new = x_values.copy()
x_values_new[target_var] += delta_x
log_y_new = beta_0
log_y_new += sum(beta_values_without_interaction[var]...
for var in beta_values_without_interaction if var in ...
log_y_new += sum(interaction_coeffs[interaction] * x_...
for interaction in interaction_coeffs if interaction ...
# 3. 寄与率の計算
y_original = np.exp(log_y)
y_new = np.exp(log_y_new)
contribution_rate = ((y_new - y_original) / y_origina...
return contribution_rate
# ======== すべての住所に対する寄与率計算 ========
output_folder = "C:/Users/tn011/Desktop/統計正しいほ...
率"
os.makedirs(output_folder, exist_ok=True)
# すべての住所を取得
target_addresses = df_toyama_data['住所'].unique()
# 各住所に対する寄与率を計算
for target_address in target_addresses:
# 住所ごとのデータをフィルタリング
target_data = df_toyama_data[df_toyama_data['住所'] =...
# 数値カラムのみを抽出して平均を計算
target_data_numeric = target_data.select_dtypes(inclu...
# 住所ごとのデータを取得
x_values = target_data_numeric.to_dict()
# 寄与率を計算する対象の変数を取得
target_vars = list(x_values.keys())
# 各住所の変数ごとの寄与率を計算
contributions = {var: compute_contribution(x_values,
beta_values_without_interaction, interaction_coeffs, ...
target_vars}
# 結果をデータフレームにまとめる
result_df = pd.DataFrame([{'住所': target_address, **...
# CSVファイルとして保存
result_file_path = os.path.join(output_folder, f"{tar...
result_df.to_csv(result_file_path, index=False, encod...
print(f"{target_address} の寄与率が保存されました: {r...
~
「''町ごとの寄与率''」フォルダーにそれぞれの町の寄与率のc...
#ref(kiyo.png,,30%)
#ref(kiyor.png,,50%)
*寄与率のGISによる可視化 [#v6998bc5]
ドライブにあるWeb-GISフォルダを統計正しいほうのフォルダに...
#ref(Web-GIS.png,,30%)
おわり
ページ名: