共计 5137 个字符,预计需要花费 13 分钟才能阅读完成。
原文链接:http://tecdat.cn/?p=21467
目标
房价无关的数据可能反映了中国近年来的变动:
- 人们失去更多的资源(薪水),冀望有更好的房子
- 人口众多
- 独生子女政策:如何影响房子的几何构造?更多的卧室,更多的空间
我外围的想法是预测房价。然而,我不打算应用任何 arima 模型;相同,我将应用数据的个性逐年拟合回归。
构造如下:
- 数据筹备:将数值特色转换为分类;缺失值
- EDA: 对于数值特色和分类特色: 平均价格与这些特色的体现
-
建模:
- 宰割训练 / 测试给定年份的数据:例如,在 2000 年宰割数据;依据这些数据训练回归模型
- 而后,在 2016 年之前的所有新年里,预测每套房子的价值。
- 用于验证的度量将是屋宇的平均价格(即每年从测试样本中取得平均价格和预测值)
数据筹备
咱们对特色有了十分残缺的形容:
url:获取数据(字符)的 url
id:id(字符)
Lng:和 Lat 坐标,应用 BD09 协定。(数字)
Cid:社区 id(数字)
交易工夫:交易工夫(字符)
DOM:市场沉闷日。(数字)
关注者:交易后的人数。(数字)
总价:(数值)
价格:按平方计算的平均价格(数值)
面积:屋宇的平方(数字)
- 起居室
:客厅数(字符)
- 客厅
:客厅数(字符)
厨房:厨房数量(数字)
浴室数量(字符)
房子的高度
修建类型:包含塔楼(1)、平房(2)、板塔组合(3)、板(4)(数值)
施工工夫
装修:包含其余(1)、粗(2)、简略(3)、简装(4)(数值)
修建构造:包含未清(1)、混合(2)、砖和木(3)、砖混凝土(4)、钢(5)和钢 - 混凝土复合材料(6)。(数值)
梯梯比:同层居民数与电梯数量的比例。
电梯有(1)或没有电梯(0)(数值)
五年期:业主领有不到 5 年的财产(数字)
数据清理、特色创立
从最后的数据看:
- 从网址上,我发现它有地位信息,如 chengjiao/101084782030。同样,一个简略的 regexp 进行省特征提取。
- 另一个大的数据筹备工作是转换一些数字特色,比方地铁,地铁站左近的家庭编码为 1,相同的状况编码为 0。
- 还有很大一部分 DOM 缺失。我既不能在建模中应用这个个性,也不能删除 NA,但它也会减小数据帧的大小。
#从网址中提取省份
sapply(df$url, function(x) strsplit(x,'/')[[1]][4])
查看缺失
# 缺失数据图
ggplot(data = .,aes(x = V2, y = V1)) + geom_tile(aes(fill = value)) +
- 如上所述,DOM 的很大一部分失落了。我决定先保留这个个性,而后用两头值来填充缺失的值(散布是十分歪斜的)
- 否则,buildingType 和 communityAverage(pop.)中只有几个短少的值,我决定简略地删除这些值。事实上,它们只占了约 30 行,而整个数据集的数据量为 300k+,因而损失不会太大。
- 上面我简略地删除了我当前不打算应用的特色。
ifelse(is.na(df$DOM),median(df$DOM,na.rm=T),df$DOM)
用于将数字转换为类别的自定义函数
对于某些特色,须要一个函数来解决多个标签,对于其余一些特色(客厅、客厅和浴室),转换非常简单。
df2$livingRoom <- as.numeric(df2$livingRoom)
仿佛 buildingType 具备谬误的编码数字值:
buildingType
count
0.048
4
0.125
3
0.250
2
0.333
5
0.375
1
0.429
1
0.500
15
0.667
1
1.000
84541
2.000
137
3.000
59715
4.000
172405
NaN
2021
因为谬误的编码值和 NA 的数量很少,因而我将再次抛弃这些行
df2$renovationCondition <- sapply(df2$renovationCondition, ionCondition)
df2$buildingStructure <- sapply(df2$buildingStructure, makeStructure)
df2$elevator <- ifelse(df2$elevator==1,'has_elevator','no_elevator')
缺失值检察
# 缺失数据图
df2 %>% is.na %>% melt %>%
ggplot(data = .,aes(x = Var2, y = Var1)) + geom_tile(aes(fill = value)) +
scale_fill_manual(values = c("grey20","white")) + theme_minimal(14) +
kable(df %>% group_by(constructionTime) %>% summarise(count=n()) %>% arrange(-count) %>% head(5))
constructionTime
count
2004
21145
2003
19409
NA
19283
2005
18924
2006
14854
df3 <- data.frame(df2 %>% na.omit())
插补后的最终查看
any(is.na(df3))
## [1] FALSE
探索性剖析
因为有数字和分类特色,我将应用的 EDA 技术有:
- 数值:相关矩阵
- 分类:箱线图和地图
咱们必须关注价格(单位价格 / 单位价格)以及总价格(百万元)
totalPrice 将是回归模型的指标变量。
数值特色
corrplot(cor(
df3 ,
tl.col='black')
评论
- totalPrice 与 communityAverage 有很强的正相干关系,即人口密集区的房价较高
- totalPrice 与客厅、卫浴室数量有肯定的正相干关系。
- 至于面积变量,咱们看到它与上述变量也有很强的相关性:这是有情理的,因为如果房子的面积大,能够建造更多的房间(不言而喻)。
- 其余一些乏味的相关性:communityAverage 与修建工夫呈负相关,这意味着在人口密集区建房所需的工夫更短
分类特色
地图
- 中国三级(省)地图
- 我看了看城郊,它位于北京左近,所以我过滤了那个特定省份的地图
ggplot() +
geom_polygon(data = shapefile_test,aes(x = long, y = lat, group = group),
BeijingLoc <- data.frame('Long'=116.4075,'Lat' = 39.904)
修建构造
makeEDA('buildingStructure')
砖木结构的屋宇是最低廉的,简直是其余类型屋宇的两倍
修建类型
makeEDA('buildingType')
平房是最低廉的,也是最本地化的
装修条件
电梯
- 价格对电梯的依赖性十分小
- 住宅的散布与这一特色是绝对相等的。
地铁
- 价格对地铁站左近的依赖性十分小。
- 住宅的散布与这一特色是绝对相等的。
是否满_五年_
makeFeatureCatEDA('fiveYearsProperty', length(unique(df3$fiveYearsProperty)))
- 对于是否领有不到 5 年房产来说,价格的依赖性的确很小
- 就这一特色而言,家庭的散布是绝对平等的
区域
回归模型
策略
- 从 tradeTime 中提取年份和月份
按年度和月份分组,失去屋宇的数量和均价
-
拆分数据集:
- 对于年[2010-2017]= 在这组年上训练并运行回归模型
- 对于 >2017 年:逐月对测试样本并预测平均价格
平均价格总览
首先咱们须要看看咱们想要预测什么
df3$year <- year(df3$tradeTimeTs)
df3$month <- month(df3$tradeTimeTs)
df3 %>% filter(year>2009) %>% group_by(monthlyTrad) %>%
summarise(count=n(), mean = mean(price)) %>%
ggplot(aes(x=monthlyTradeTS, y= mean)) +
- 均匀价格上涨至 2017 年中期,而后迅速降落
- 同时,屋宇数量随着价格的上涨而减少,而且当初房屋交易的数量也随着价格的上涨而缩小。
筹备训练 / 测试样本
我在 2017-01-01 拆分数据。对于所有样本,我须要把分类特色变成伪变量。
df_train <- data.frame(df %>% filter(year>2009 & year<2017))
df_test <- data.frame(df %>% filter(year>=2017))
as.data.frame(cbind(df_train %>% select_if(is.numeric) %>% select(-Lng, -Lat, -year, -month),
'bldgType'= dummy.code(df_train$buildingType),
'bldgStruc'= dummy.code(df_train$buildingStructure),
'renovation'= dummy.code(df_train$renovationCondition),
'hasElevator'= dummy.code(df_train$elevator),
在这一步中,我只训练一个线性模型
regressors<-c('lm')
Control <- trainControl(method = "cv",number = 5, repeats=3)
for(r in regressors){
cnt<-cnt+1
res[[cnt]]<-train(totalPrice ~., data = train ,method=r,trControl = Control)
r^2 在 0.88 左右,不错。让咱们看看细节。
训练精度
g1<-ggplot(data=PRED,aes(x=Prediction,y=True)) + geom_jitter() + geom_smooth(method='lm',size=.5) +
#计算指标
mse <- mean((PRED$True-PRED$Prediction)^2)
rmse<-mse^0.5
SSE = sum((PRED$Pred - PR
## [1] "MSE: 15952.845934 RMSE : 126.304576 R2 :0.795874"
- 所以看起来残差还不错(散布是正态的,以 0 为核心),但对于低价格来说仿佛失败了。
训练和测试样本的预测与工夫的关系
- 基本上与上述雷同,但我将反复预测所有月份的训练数据
- 我的指标指标是均匀房价。
- 训练是在 10 多年的训练样本中实现的,因而逐月查看预测将十分乏味。
# 训练样本 -> 训练精度
for (i in 1:length(dates_train)){current_df <- prepareDF(current_df)
current_pred <- mean(predict(res[[1]],current_df))
#运行测试样本 --> 测试精度
for (i in 1:length(dates_test)){current_df <- prepareDF(current_df)
current_pred <- mean(predict(res[[1]],current_df))
RES %>% reshape2::melt(id=c('date','split')) %>%
ggplot(aes(x=date,y=value)) + geom_line(aes(color=variable, lty=split),size=1) +
- 预测对于 2012 年之后的数据的确十分好,这可能与有足够数据的月份绝对应
改良 / 要做
地理位置作为特色
- 上面是一个乏味的图;它显示了每个地位的总价格。在二维散布的核心,价格更高。
- 这个想法是计算每个房子到核心的间隔,并关联一个等级 / 分数
BeijingLoc <- data.frame('Long'=116.4075,'Lat' = 39.904)
df3 %>% ggplot(aes(x=Lng,y=Lat)) + geom_point(aes(color=price),size=.1,alpha=.5) +
theme(legend.position = 'bottom') +
最受欢迎的见解
1.R 语言多元 Logistic 逻辑回归 利用案例
2. 面板平滑转移回归 (PSTR) 剖析案例实现
3.matlab 中的偏最小二乘回归(PLSR)和主成分回归(PCR)
4.R 语言泊松 Poisson 回归模型剖析案例
5.R 语言回归中的 Hosmer-Lemeshow 拟合优度测验
6.r 语言中对 LASSO 回归,Ridge 岭回归和 Elastic Net 模型实现
7. 在 R 语言中实现 Logistic 逻辑回归
8.python 用线性回归预测股票价格
9.R 语言如何在生存剖析与 Cox 回归中计算 IDI,NRI 指标