東京都の不動産市場は、地域特性・法規制・物件属性など多様な要因によって価格が決定される複雑な市場である。 本分析では、国土交通省が公表している「不動産取引価格情報」(宅地・土地と建物、東京都、2024年第1〜4四半期)を用いて、 価格決定要因を実証的に分析する。
分析結果の応用として、実在する中古戸建物件(東京都新宿区原町1丁目、都営大江戸線「牛込柳町」駅徒歩1分、 木造3階建・土地43.75㎡・延床64.24㎡・2023年2月築・販売価格1億4800万円)を対象に、 推定モデルによる市場適正価格の予測値と実際の販売価格を比較する。
回帰モデルを推定することにより、以下の問いに答える。
library(tidyverse)
library(stargazer)
library(knitr)
library(kableExtra)
library(car) # VIF計算用
library(patchwork) # 図の並列表示用
library(lmtest) # coeftest用
library(sandwich) # hccm(ロバスト標準誤差)用
raw <- read.csv(
"data/residential_property_tokyo_2024.csv",
fileEncoding = "CP932",
stringsAsFactors = FALSE
)
df_raw <- raw %>%
rename(
price = `取引価格.総額.`,
area = `面積...`,
floor_area = `延床面積...`,
distance = `最寄駅.距離.分.`,
build_year = `建築年`,
structure = `建物の構造`,
municipality = `市区町村名`,
city_planning = `都市計画`
) %>%
select(price, area, floor_area, distance,
build_year, structure, municipality, city_planning)
df_clean <- df_raw %>%
mutate(
year_num = as.numeric(str_extract(build_year, "\\d{4}")),
age = 2024 - year_num
)
「30分~60分」は中間値 45 分として扱い、空白は欠損値とする。
df_clean <- df_clean %>%
mutate(
distance_num = case_when(
distance == "30分~60分" ~ 45,
distance == "" ~ NA_real_,
TRUE ~ as.numeric(distance)
)
)
df_clean <- df_clean %>%
mutate(
price = as.numeric(price),
area = as.numeric(area),
floor_area = as.numeric(floor_area)
)
price_q <- quantile(df_clean$price, c(0.01, 0.99), na.rm = TRUE)
area_q99 <- quantile(df_clean$area, 0.99, na.rm = TRUE)
dat <- df_clean %>%
filter(
!is.na(price), !is.na(area), !is.na(floor_area),
!is.na(distance_num), !is.na(age),
!is.na(structure), structure != "",
!is.na(municipality), municipality != "",
!is.na(city_planning), city_planning != "",
price >= price_q[1] & price <= price_q[2],
area >= 10 & area <= area_q99,
floor_area > 0,
age >= 0 & age <= 80
) %>%
mutate(
log_price = log(price),
structure = as.factor(structure),
municipality = as.factor(municipality),
city_planning = as.factor(city_planning)
)
cat("前処理後のサンプル数:", nrow(dat), "\n")
## 前処理後のサンプル数: 3890
多重共線性の懸念について: 容積率は都市計画区域と高い相関を持つため、回帰モデルからは除外した。
desc_vars <- dat %>%
select(price, area, floor_area, distance_num, age) %>%
rename(
"取引価格(万円)" = price,
"土地面積(㎡)" = area,
"延床面積(㎡)" = floor_area,
"駅距離(分)" = distance_num,
"築年数(年)" = age
) %>%
mutate(`取引価格(万円)` = `取引価格(万円)` / 1e4)
desc_table <- data.frame(
変数 = names(desc_vars),
平均 = sapply(desc_vars, mean),
標準偏差 = sapply(desc_vars, sd),
最小値 = sapply(desc_vars, min),
第1四分位 = sapply(desc_vars, function(x) quantile(x, 0.25)),
中央値 = sapply(desc_vars, median),
第3四分位 = sapply(desc_vars, function(x) quantile(x, 0.75)),
最大値 = sapply(desc_vars, max)
)
kable(desc_table,
digits = 2,
caption = "表:主要変数の要約統計(N = 3,890)",
row.names = FALSE)
| 変数 | 平均 | 標準偏差 | 最小値 | 第1四分位 | 中央値 | 第3四分位 | 最大値 |
|---|---|---|---|---|---|---|---|
| 取引価格(万円) | 5836.63 | 3227.42 | 800 | 3700 | 5200 | 7100 | 21000 |
| 土地面積(㎡) | 100.09 | 43.08 | 25 | 70 | 95 | 120 | 280 |
| 延床面積(㎡) | 99.80 | 30.21 | 30 | 85 | 95 | 110 | 440 |
| 駅距離(分) | 13.46 | 5.68 | 5 | 10 | 15 | 15 | 45 |
| 築年数(年) | 17.74 | 14.28 | 0 | 6 | 15 | 26 | 76 |
dat %>% group_by(structure) %>%
summarise(n = n(), median_price_man = median(price) / 1e4) %>%
kable(caption = "建物構造の内訳と中央値価格(万円)")
| structure | n | median_price_man |
|---|---|---|
| RC | 64 | 9700 |
| SRC | 2 | 10250 |
| ブロック造 | 1 | 5600 |
| 軽量鉄骨造 | 185 | 6300 |
| 鉄骨造 | 118 | 6650 |
| 木造 | 3520 | 5100 |
注意: SRC(2件)・ブロック造(1件)は件数が非常に少なく、回帰係数が不安定になりやすい。 特にブロック造は1件のみであり、係数の解釈には十分な注意が必要である(付録1参照)。
p1 <- ggplot(dat, aes(x = price / 1e4)) +
geom_histogram(bins = 50, fill = "steelblue", color = "white", alpha = 0.8) +
labs(x = "取引価格(万円)", y = "頻度", title = "取引価格(水準)")
p2 <- ggplot(dat, aes(x = log_price)) +
geom_histogram(bins = 50, fill = "tomato", color = "white", alpha = 0.8) +
labs(x = "log(取引価格)", y = "頻度", title = "取引価格(対数変換後)")
p1 + p2
図1:取引価格の分布(左:水準, 右:対数)
cor(dat[, c("price", "area", "floor_area", "distance_num", "age")])
## price area floor_area distance_num age
## price 1.0000000 0.1527376 0.44890439 -0.26267912 -0.24434799
## area 0.1527376 1.0000000 0.59082719 0.20433846 0.10500250
## floor_area 0.4489044 0.5908272 1.00000000 -0.00725058 0.05733891
## distance_num -0.2626791 0.2043385 -0.00725058 1.00000000 -0.02857845
## age -0.2443480 0.1050025 0.05733891 -0.02857845 1.00000000
par(family = if (knitr::is_latex_output()) "IPAexGothic" else "")
plot(dat[, c("price", "area", "floor_area", "distance_num", "age")],
labels = c("Price", "Area", "Floor area", "Distance", "Age"),
pch = 20, cex = 0.3)
図2:主要変数の散布図行列
| モデル | 説明変数 |
|---|---|
| Model 1(ベース) | 面積・延床面積・駅距離・築年数・建物構造 |
| Model 2(地域効果) | Model 1 + 市区町村固定効果 |
| Model 3(法規制効果) | Model 1 + 都市計画固定効果 |
| Model 4(統合モデル) | Model 1 + 市区町村 + 都市計画 |
m1 <- lm(log_price ~ area + floor_area + distance_num + age + structure,
data = dat)
m2 <- lm(log_price ~ area + floor_area + distance_num + age + structure
+ municipality,
data = dat)
m3 <- lm(log_price ~ area + floor_area + distance_num + age + structure
+ city_planning,
data = dat)
m4 <- lm(log_price ~ area + floor_area + distance_num + age + structure
+ municipality + city_planning,
data = dat)
各カテゴリ変数の基準カテゴリは以下のとおりである。 建物構造の基準カテゴリはRC造、市区町村の基準カテゴリはRのデフォルト因子順(五十音順)による先頭の市区町村である。 基準市区町村を以下のコードで確認する。
# 建物構造の基準カテゴリ
levels(dat$structure)[1]
## [1] "RC"
# 市区町村の基準カテゴリ
levels(dat$municipality)[1]
## [1] "あきる野市"
summary(m2)
##
## Call:
## lm(formula = log_price ~ area + floor_area + distance_num + age +
## structure + municipality, data = dat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.47442 -0.13081 0.00884 0.14158 1.07577
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 16.4965681 0.0621248 265.539 < 0.0000000000000002
## area 0.0038698 0.0001530 25.287 < 0.0000000000000002
## floor_area 0.0046604 0.0001899 24.544 < 0.0000000000000002
## distance_num -0.0139060 0.0007637 -18.209 < 0.0000000000000002
## age -0.0171735 0.0002841 -60.451 < 0.0000000000000002
## structureSRC 0.1223114 0.1751752 0.698 0.485080
## structureブロック造 1.3129548 0.2480225 5.294 0.00000012659506
## structure軽量鉄骨造 -0.0116711 0.0361021 -0.323 0.746500
## structure鉄骨造 -0.0323831 0.0383430 -0.845 0.398407
## structure木造 -0.1534317 0.0318826 -4.812 0.00000154877104
## municipality稲城市 0.7252332 0.0652170 11.120 < 0.0000000000000002
## municipality羽村市 0.3626559 0.0848545 4.274 0.00001967946069
## municipality葛飾区 0.8376497 0.0531546 15.759 < 0.0000000000000002
## municipality江戸川区 0.9510757 0.0514997 18.468 < 0.0000000000000002
## municipality江東区 1.1678904 0.0569786 20.497 < 0.0000000000000002
## municipality港区 2.1864642 0.1193272 18.323 < 0.0000000000000002
## municipality荒川区 1.1404920 0.0611940 18.637 < 0.0000000000000002
## municipality国分寺市 0.9604468 0.0562357 17.079 < 0.0000000000000002
## municipality国立市 0.9878298 0.0697378 14.165 < 0.0000000000000002
## municipality狛江市 0.9749431 0.0619840 15.729 < 0.0000000000000002
## municipality三鷹市 1.1805906 0.0577285 20.451 < 0.0000000000000002
## municipality渋谷区 1.7831626 0.0684931 26.034 < 0.0000000000000002
## municipality小金井市 1.0408575 0.0558477 18.637 < 0.0000000000000002
## municipality小平市 0.7308418 0.0544489 13.423 < 0.0000000000000002
## municipality昭島市 0.5348000 0.0637666 8.387 < 0.0000000000000002
## municipality新宿区 1.5562999 0.0595247 26.145 < 0.0000000000000002
## municipality杉並区 1.4053625 0.0507315 27.702 < 0.0000000000000002
## municipality世田谷区 1.5214923 0.0501201 30.357 < 0.0000000000000002
## municipality清瀬市 0.5030555 0.0723525 6.953 0.00000000000419
## municipality西多摩郡瑞穂町 -0.0727100 0.0904550 -0.804 0.421548
## municipality西東京市 0.8724798 0.0544320 16.029 < 0.0000000000000002
## municipality青梅市 0.0486512 0.0575031 0.846 0.397571
## municipality足立区 0.7797171 0.0508742 15.326 < 0.0000000000000002
## municipality多摩市 0.6366086 0.0609327 10.448 < 0.0000000000000002
## municipality台東区 1.4193719 0.1106273 12.830 < 0.0000000000000002
## municipality大田区 1.2678384 0.0512232 24.751 < 0.0000000000000002
## municipality中央区 1.5248362 0.1792588 8.506 < 0.0000000000000002
## municipality中野区 1.3299461 0.0554235 23.996 < 0.0000000000000002
## municipality町田市 0.6077544 0.0514183 11.820 < 0.0000000000000002
## municipality調布市 1.0233285 0.0551002 18.572 < 0.0000000000000002
## municipality東久留米市 0.6539178 0.0599102 10.915 < 0.0000000000000002
## municipality東村山市 0.5148567 0.0549533 9.369 < 0.0000000000000002
## municipality東大和市 0.4172005 0.0630689 6.615 0.00000000004230
## municipality日野市 0.4859646 0.0557718 8.713 < 0.0000000000000002
## municipality八王子市 0.3417011 0.0522328 6.542 0.00000000006878
## municipality板橋区 1.0369205 0.0524905 19.754 < 0.0000000000000002
## municipality品川区 1.4890239 0.0560438 26.569 < 0.0000000000000002
## municipality府中市 0.8006421 0.0547951 14.612 < 0.0000000000000002
## municipality武蔵村山市 0.3493247 0.0748723 4.666 0.00000318216055
## municipality武蔵野市 1.4395999 0.0675545 21.310 < 0.0000000000000002
## municipality福生市 0.2587313 0.0705492 3.667 0.000248
## municipality文京区 1.7707152 0.0644230 27.486 < 0.0000000000000002
## municipality豊島区 1.4249432 0.0576946 24.698 < 0.0000000000000002
## municipality北区 1.1105343 0.0566208 19.614 < 0.0000000000000002
## municipality墨田区 1.1348670 0.0583650 19.444 < 0.0000000000000002
## municipality目黒区 1.7590893 0.0557982 31.526 < 0.0000000000000002
## municipality立川市 0.6522864 0.0591665 11.025 < 0.0000000000000002
## municipality練馬区 1.1292005 0.0504649 22.376 < 0.0000000000000002
##
## (Intercept) ***
## area ***
## floor_area ***
## distance_num ***
## age ***
## structureSRC
## structureブロック造 ***
## structure軽量鉄骨造
## structure鉄骨造
## structure木造 ***
## municipality稲城市 ***
## municipality羽村市 ***
## municipality葛飾区 ***
## municipality江戸川区 ***
## municipality江東区 ***
## municipality港区 ***
## municipality荒川区 ***
## municipality国分寺市 ***
## municipality国立市 ***
## municipality狛江市 ***
## municipality三鷹市 ***
## municipality渋谷区 ***
## municipality小金井市 ***
## municipality小平市 ***
## municipality昭島市 ***
## municipality新宿区 ***
## municipality杉並区 ***
## municipality世田谷区 ***
## municipality清瀬市 ***
## municipality西多摩郡瑞穂町
## municipality西東京市 ***
## municipality青梅市
## municipality足立区 ***
## municipality多摩市 ***
## municipality台東区 ***
## municipality大田区 ***
## municipality中央区 ***
## municipality中野区 ***
## municipality町田市 ***
## municipality調布市 ***
## municipality東久留米市 ***
## municipality東村山市 ***
## municipality東大和市 ***
## municipality日野市 ***
## municipality八王子市 ***
## municipality板橋区 ***
## municipality品川区 ***
## municipality府中市 ***
## municipality武蔵村山市 ***
## municipality武蔵野市 ***
## municipality福生市 ***
## municipality文京区 ***
## municipality豊島区 ***
## municipality北区 ***
## municipality墨田区 ***
## municipality目黒区 ***
## municipality立川市 ***
## municipality練馬区 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2429 on 3832 degrees of freedom
## Multiple R-squared: 0.8132, Adjusted R-squared: 0.8104
## F-statistic: 292.6 on 57 and 3832 DF, p-value: < 0.00000000000000022
都市計画FEは,国交省データの「都市計画」欄に入るカテゴリ(本データでは準工業地域・近隣商業地域などの用途地域系カテゴリ)の固定効果であり,都市計画区域内ダミー(0/1)ではない。Model 4 における各カテゴリの係数は以下のとおりである。
coef_m4 <- summary(m4)$coefficients
cityplan_rows <- grep("^city_planning", rownames(coef_m4))
round(coef_m4[cityplan_rows, ], 4)
## Estimate Std. Error t value Pr(>|t|)
## city_planning1中住専 0.0062 0.0150 0.4171 0.6766
## city_planning1低住専 -0.0086 0.0153 -0.5616 0.5744
## city_planning2種住居 0.1475 0.0663 2.2250 0.0261
## city_planning2中住専 0.0123 0.0323 0.3823 0.7023
## city_planning2低住専 0.0154 0.0446 0.3449 0.7302
## city_planning近隣商業 0.0426 0.0223 1.9089 0.0563
## city_planning工業 -0.0841 0.0538 -1.5636 0.1180
## city_planning工業専用 -0.2722 0.2434 -1.1182 0.2636
## city_planning準工業 -0.0430 0.0180 -2.3960 0.0166
## city_planning準住居 -0.1213 0.0491 -2.4680 0.0136
stargazer(
m1, m2, m3, m4,
type = out_type,
title = "表1:回帰分析結果(被説明変数:log(取引価格))",
column.labels = c("(1) Base", "(2) +Municipality", "(3) +CityPlan", "(4) Integrated"),
covariate.labels = c(
"土地面積(㎡)",
"延床面積(㎡)",
"駅距離(分)",
"築年数(年)",
"建物構造:SRC",
"建物構造:ブロック造",
"建物構造:軽量鉄骨造",
"建物構造:鉄骨造",
"建物構造:木造"
),
omit = c("municipality", "city_planning"),
add.lines = list(
c("市区町村FE", "No", "Yes", "No", "Yes"),
c("都市計画FE", "No", "No", "Yes", "Yes")
),
omit.stat = c("f", "ser"),
digits = 4,
star.cutoffs = c(0.05, 0.01, 0.001),
notes = "* p<0.05, ** p<0.01, *** p<0.001. 建物構造の基準カテゴリ:RC造",
notes.append = FALSE,
header = FALSE,
no.space = TRUE,
font.size = "small"
)
| Dependent variable: | ||||
| log_price | ||||
|
|
|
|
|
| (1) | (2) | (3) | (4) | |
| 土地面積(㎡) | -0.0010*** | 0.0039*** | -0.0021*** | 0.0039*** |
| (0.0002) | (0.0002) | (0.0002) | (0.0002) | |
| 延床面積(㎡) | 0.0085*** | 0.0047*** | 0.0093*** | 0.0046*** |
| (0.0003) | (0.0002) | (0.0003) | (0.0002) | |
| 駅距離(分) | -0.0251*** | -0.0139*** | -0.0259*** | -0.0137*** |
| (0.0012) | (0.0008) | (0.0012) | (0.0008) | |
| 築年数(年) | -0.0169*** | -0.0172*** | -0.0168*** | -0.0172*** |
| (0.0005) | (0.0003) | (0.0005) | (0.0003) | |
| 建物構造:SRC | 0.1067 | 0.1223 | 0.0815 | 0.1048 |
| (0.3013) | (0.1752) | (0.2958) | (0.1749) | |
| 建物構造:ブロック造 | 1.1235** | 1.3130*** | 1.2825** | 1.3047*** |
| (0.4241) | (0.2480) | (0.4165) | (0.2478) | |
| 建物構造:軽量鉄骨造 | -0.1654** | -0.0117 | -0.1221* | -0.0110 |
| (0.0618) | (0.0361) | (0.0607) | (0.0360) | |
| 建物構造:鉄骨造 | -0.3231*** | -0.0324 | -0.2464*** | -0.0277 |
| (0.0652) | (0.0383) | (0.0644) | (0.0384) | |
| 建物構造:木造 | -0.3385*** | -0.1534*** | -0.3079*** | -0.1537*** |
| (0.0545) | (0.0319) | (0.0535) | (0.0318) | |
| Constant | 17.9554*** | 16.4966*** | 17.9087*** | 16.4918*** |
| (0.0653) | (0.0621) | (0.0661) | (0.0631) | |
| 市区町村FE | No | Yes | No | Yes |
| 都市計画FE | No | No | Yes | Yes |
| Observations | 3,890 | 3,890 | 3,890 | 3,890 |
| R2 | 0.4359 | 0.8132 | 0.4591 | 0.8147 |
| Adjusted R2 | 0.4346 | 0.8104 | 0.4564 | 0.8114 |
| Note: |
|
|||
m_vif <- lm(log_price ~ area + floor_area + distance_num + age, data = dat)
vif(m_vif)
## area floor_area distance_num age
## 1.662664 1.578035 1.074740 1.014037
図3の残差診断(後掲)から、当てはめ値が大きい領域で残差のばらつきがやや拡大する 傾向が見られる。OLS標準誤差は不均一分散のもとで一致性を持つものの非効率であり、 t値・p値の信頼性が低下する可能性がある。 以下ではHC1型ロバスト標準誤差(heteroscedasticity-consistent covariance matrix)を用いて 主要係数の有意性を再確認する。 なお、HC3型はブロック造(1件)の観測値においてレバレッジ値が1に近く \((1 - h_{ii})^2 \approx 0\)となるため分散の推定値がNaNになる。 そのため本分析ではHC1型を採用した。
# HC1型ロバスト標準誤差によるModel 2の再推定
# (HC3はブロック造1件のレバレッジ≒1により分母≒0となりNaNが生じるためHC1を使用)
coeftest_robust <- coeftest(m2, vcov = vcovHC(m2, type = "HC1"))
# 主要な連続変数のみ抜粋して比較
rows_key <- c("area", "floor_area", "distance_num", "age")
comparison_se <- data.frame(
変数 = c("土地面積", "延床面積", "駅距離", "築年数"),
OLS係数 = round(coef(m2)[rows_key], 5),
OLS標準誤差 = round(summary(m2)$coefficients[rows_key, "Std. Error"], 5),
OLS_p値 = round(summary(m2)$coefficients[rows_key, "Pr(>|t|)"], 5),
Robust標準誤差 = round(coeftest_robust[rows_key, "Std. Error"], 5),
Robust_p値 = round(coeftest_robust[rows_key, "Pr(>|t|)"], 5)
)
kable(comparison_se,
caption = "表2:OLS標準誤差とHC1型ロバスト標準誤差の比較(Model 2)",
row.names = FALSE)
| 変数 | OLS係数 | OLS標準誤差 | OLS_p値 | Robust標準誤差 | Robust_p値 |
|---|---|---|---|---|---|
| 土地面積 | 0.00387 | 0.00015 | 0 | 0.00022 | 0 |
| 延床面積 | 0.00466 | 0.00019 | 0 | 0.00033 | 0 |
| 駅距離 | -0.01391 | 0.00076 | 0 | 0.00077 | 0 |
| 築年数 | -0.01717 | 0.00028 | 0 | 0.00038 | 0 |
par(mfrow = c(1, 2), family = if (knitr::is_latex_output()) "IPAexGothic" else "")
plot(fitted(m2), residuals(m2),
xlab = "当てはめ値(fitted values)",
ylab = "残差(residuals)",
main = "残差 vs. 当てはめ値",
pch = 16, cex = 0.4, col = adjustcolor("steelblue", alpha.f = 0.4))
abline(h = 0, col = "red", lty = 2)
qqnorm(residuals(m2),
main = "QQプロット(残差の正規性)",
pch = 16, cex = 0.4, col = adjustcolor("tomato", alpha.f = 0.4))
qqline(residuals(m2), col = "red", lty = 2)
図3:Model 2 の残差診断
par(mfrow = c(1, 1))
実在する中古戸建物件(SUUMO掲載、情報提供日:2026年4月13日)を対象とする。
| 属性 | 値 |
|---|---|
| 所在地 | 東京都新宿区原町1丁目 |
| 最寄駅 | 都営大江戸線「牛込柳町」駅 徒歩1分 |
| 土地面積 | 43.75 ㎡ |
| 延床面積 | 64.24 ㎡ |
| 築年数 | 1年(2023年2月築、基準年2024年) |
| 建物構造 | 木造 |
| 市区町村 | 新宿区 |
| 販売価格(実績) | 1億4800万円 |
築年数の処理について: 本物件は2023年2月築であり、データの基準年2024年との差は厳密には 取引時期に応じて1〜2年の間となる。本分析では保守的に
age = 1(最小値)を採用しており、 築年数をわずかに若く見積もっているため、予測価格はやや上方バイアスを持つ可能性がある。
Step 1. 対数価格を予測する。
\[ \log\hat{y}_V = \hat{\beta}_0 + 0.0039 \times 43.75 + 0.0047 \times 64.24 - 0.0139 \times 1 - 0.0172 \times 1 + (\text{木造係数}) + (\text{新宿区係数}) \]
Step 2. 誤差項 \(\epsilon_i \sim N(0, \sigma^2)\) を仮定すると \(E[\exp(\epsilon_i)] = \exp(\sigma^2/2)\) が成立するため、 元の価格スケールへの変換時に補正が必要である。
\[ \hat{y}_V = \exp\!\left(\log\hat{y}_V + \frac{\hat{\sigma}^2}{2}\right) \]
# ターゲット物件の属性(実在物件:新宿区原町1丁目)
target <- data.frame(
area = 43.75,
floor_area = 64.24,
distance_num = 1,
age = 1, # 2023年2月築、基準年2024年(保守的にage=1を採用)
structure = factor("木造", levels = levels(dat$structure)),
municipality = factor("新宿区", levels = levels(dat$municipality))
)
# 対数価格の予測値
log_price_hat <- predict(m2, newdata = target)
log_price_hat
## 1
## 18.33705
# 残差標準誤差と残差分散
summary(m2)$sigma
## [1] 0.2428674
sigma2_hat <- summary(m2)$sigma^2
sigma2_hat
## [1] 0.05898456
# 補正なし予測価格(万円)
exp(log_price_hat) / 1e4
## 1
## 9197.669
# 補正あり予測価格(万円):E[y] の不偏推定
price_pred_corrected_man <- exp(log_price_hat + sigma2_hat / 2) / 1e4
price_pred_corrected_man
## 1
## 9472.969
# 95% 予測区間(万円)
pred_interval <- predict(m2, newdata = target,
interval = "prediction", level = 0.95)
exp(pred_interval) / 1e4
## fit lwr upr
## 1 9197.669 5685.17 14880.31
# 実際の販売価格
actual_price_man <- 14800
cat("予測値(補正あり):", round(price_pred_corrected_man, 0), "万円\n")
## 予測値(補正あり): 9473 万円
cat("実際の販売価格: ", actual_price_man, "万円\n")
## 実際の販売価格: 14800 万円
cat("差(予測 - 実際): ", round(price_pred_corrected_man - actual_price_man, 0), "万円\n")
## 差(予測 - 実際): -5327 万円
price_pred_corrected <- exp(log_price_hat + sigma2_hat / 2)
pi_lower <- exp(pred_interval[, "lwr"])
pi_upper <- exp(pred_interval[, "upr"])
similar <- dat %>%
filter(structure == "木造", municipality == "新宿区")
cat("木造・新宿区のサンプル数:", nrow(similar), "\n")
## 木造・新宿区のサンプル数: 46
ggplot(similar, aes(x = price / 1e4)) +
geom_histogram(bins = 20, fill = "steelblue", alpha = 0.6, color = "white") +
geom_vline(xintercept = price_pred_corrected / 1e4,
color = "red", linewidth = 1.2, linetype = "solid") +
geom_vline(xintercept = actual_price_man,
color = "darkgreen", linewidth = 1.2, linetype = "solid") +
geom_vline(xintercept = pi_lower / 1e4,
color = "orange", linewidth = 0.8, linetype = "dashed") +
geom_vline(xintercept = pi_upper / 1e4,
color = "orange", linewidth = 0.8, linetype = "dashed") +
annotate("text",
x = price_pred_corrected / 1e4,
y = Inf, vjust = 2, hjust = 1.1,
label = paste0("予測値\n", round(price_pred_corrected / 1e4, 0), "万円"),
color = "red", size = 3.5) +
annotate("text",
x = actual_price_man,
y = Inf, vjust = 4, hjust = -0.1,
label = paste0("販売価格\n", actual_price_man, "万円"),
color = "darkgreen", size = 3.5) +
labs(x = "取引価格(万円)", y = "件数",
title = "予測価格と実績分布の比較(木造・新宿区)",
caption = "赤線: 補正済み予測値, 緑線: 実際の販売価格, オレンジ破線: 95%予測区間\n※木造・新宿区のサンプルは限られるため分布の形状の解釈には注意が必要")
図4:予測価格・実際価格と95%予測区間(同属性物件の実績分布との比較)。木造・新宿区のサンプルは限られるため、分布の形状の解釈には注意が必要である。
SRC(2件)およびブロック造(1件)はサンプル数が極端に少なく、Model 2 における推定値が不安定である可能性が高い(特にブロック造の係数は約 1.31 と不自然に大きい)。以下では、これら2つの構造を「その他」カテゴリに統合し、主要な連続変数および建物構造の各係数への影響を確認する。
library(forcats)
# SRCとブロック造を「その他」に統合
dat_sens4 <- dat %>%
mutate(structure_sens = fct_collapse(structure,
"その他" = c("SRC", "ブロック造")))
m2_sens4 <- lm(log_price ~ area + floor_area + distance_num + age +
structure_sens + municipality,
data = dat_sens4)
# 比較する変数のリスト
rows_orig <- c("area", "floor_area", "distance_num", "age",
"structure軽量鉄骨造", "structure鉄骨造", "structure木造")
rows_sens <- c("area", "floor_area", "distance_num", "age",
"structure_sens軽量鉄骨造", "structure_sens鉄骨造", "structure_sens木造")
coef_orig <- summary(m2)$coefficients
coef_sens <- summary(m2_sens4)$coefficients
comparison <- data.frame(
変数 = c("土地面積", "延床面積", "駅距離", "築年数",
"建物構造:軽量鉄骨造", "建物構造:鉄骨造", "建物構造:木造"),
元モデル係数 = round(coef_orig[rows_orig, "Estimate"], 5),
感度分析係数 = round(coef_sens[rows_sens, "Estimate"], 5)
)
kable(comparison, caption = "表A1:小サンプル構造統合前後の主要係数比較")
| 変数 | 元モデル係数 | 感度分析係数 | |
|---|---|---|---|
| area | 土地面積 | 0.00387 | 0.00390 |
| floor_area | 延床面積 | 0.00466 | 0.00461 |
| distance_num | 駅距離 | -0.01391 | -0.01389 |
| age | 築年数 | -0.01717 | -0.01715 |
| structure軽量鉄骨造 | 建物構造:軽量鉄骨造 | -0.01167 | -0.01329 |
| structure鉄骨造 | 建物構造:鉄骨造 | -0.03238 | -0.03233 |
| structure木造 | 建物構造:木造 | -0.15343 | -0.15511 |
cat("元モデル 調整済みR²: ", round(summary(m2)$adj.r.squared, 4), "\n")
## 元モデル 調整済みR²: 0.8104
cat("感度分析 調整済みR²: ", round(summary(m2_sens4)$adj.r.squared, 4), "\n")
## 感度分析 調整済みR²: 0.8097
target_sens4 <- data.frame(
area = 43.75,
floor_area = 64.24,
distance_num = 1,
age = 1,
structure_sens = factor("木造", levels = levels(dat_sens4$structure_sens)),
municipality = factor("新宿区", levels = levels(dat$municipality))
)
log_pred_sens4 <- predict(m2_sens4, newdata = target_sens4)
sigma2_sens4 <- summary(m2_sens4)$sigma^2
price_sens4_man <- exp(log_pred_sens4 + sigma2_sens4 / 2) / 1e4
cat("元モデル 予測価格:", round(price_pred_corrected_man, 0), "万円\n")
## 元モデル 予測価格: 9473 万円
cat("感度分析 予測価格:", round(price_sens4_man, 0), "万円\n")
## 感度分析 予測価格: 9472 万円
「30分〜60分」(269件、全体の約5%)を中間値45分として扱う現行の処理に対し、 これらを除外した場合の主要係数と R² を確認する。
dat_sens5 <- dat %>% filter(distance_num != 45)
cat("「30分~60分」除外後のサンプル数:", nrow(dat_sens5), "\n")
## 「30分~60分」除外後のサンプル数: 3875
m2_sens5 <- lm(log_price ~ area + floor_area + distance_num + age +
structure + municipality,
data = dat_sens5)
# 主要係数の比較
rows_key <- c("area", "floor_area", "distance_num", "age", "structure木造")
comparison5 <- data.frame(
変数 = c("土地面積", "延床面積", "駅距離", "築年数", "木造"),
元モデル係数 = round(coef_orig[rows_key, "Estimate"], 5),
除外時係数 = round(summary(m2_sens5)$coefficients[rows_key, "Estimate"], 5)
)
kable(comparison5, caption = "表A2:「30分〜60分」除外前後の主要係数比較")
| 変数 | 元モデル係数 | 除外時係数 | |
|---|---|---|---|
| area | 土地面積 | 0.00387 | 0.00388 |
| floor_area | 延床面積 | 0.00466 | 0.00465 |
| distance_num | 駅距離 | -0.01391 | -0.01405 |
| age | 築年数 | -0.01717 | -0.01714 |
| structure木造 | 木造 | -0.15343 | -0.15282 |
cat("元モデル 調整済みR²: ", round(summary(m2)$adj.r.squared, 4), "\n")
## 元モデル 調整済みR²: 0.8104
cat("除外モデル 調整済みR²:", round(summary(m2_sens5)$adj.r.squared, 4), "\n")
## 除外モデル 調整済みR²: 0.8094