链家二手房分析.R 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. # 导入开发所需的扩展包
  2. library(dplyr)
  3. library(Hmisc)
  4. library(ggplot2)
  5. library(caret)
  6. house <- read.csv(file.choose(), stringsAsFactors = FALSE)
  7. dim(house)
  8. str(house)
  9. summary(house)
  10. load('.RData')
  11. # 数据探索
  12. # 户型分布
  13. type_freq <- data.frame(table(house$户型))
  14. type_p <- ggplot(data = type_freq, mapping = aes(x = reorder(Var1, -Freq),y = Freq)) + geom_bar(stat = 'identity', fill = 'steelblue') + theme(axis.text.x = element_text(angle = 30, vjust = 0.5)) + xlab('户型') + ylab('套数')
  15. type_p
  16. # 把低于一千套的房型设置为其他
  17. type <- c('2室2厅','2室1厅','3室2厅','1室1厅','3室1厅','4室2厅','1室0厅','2室0厅')
  18. house$type.new <- ifelse(house$户型 %in% type, house$户型,'其他')
  19. type_freq <- data.frame(table(house$type.new))
  20. type_p <- ggplot(data = type_freq, mapping = aes(x = reorder(Var1, -Freq),y = Freq)) + geom_bar(stat = 'identity', fill = 'steelblue') + theme(axis.text.x = element_text(angle = 30, vjust = 0.5)) + xlab('户型') + ylab('套数')
  21. type_p
  22. # 面积的正态性检验
  23. norm.test(house$面积)
  24. # 房价的正态性检验
  25. norm.test(house$价格.W.)
  26. # 楼层分布
  27. unique(house$楼层)
  28. # 把楼层分为低区、中区和高区三种
  29. house$floow <- ifelse(substring(house$楼层,1,2) %in% c('低区','中区','高区'), substring(house$楼层,1,2),'低区')
  30. # 各楼层类型百分比分布
  31. percent <- paste(round(prop.table(table(house$floow))*100,2),'%',sep = '')
  32. df <- data.frame(table(house$floow))
  33. df <- cbind(df, percent)
  34. df
  35. # 上海各区房价均价
  36. avg_price <- aggregate(house$单价.平方米., by = list(house$区域), mean)
  37. p <- ggplot(data = avg_price, mapping = aes(x = reorder(Group.1, -x), y = x, group = 1)) + geom_area(fill = 'lightgreen') + geom_line(colour = 'steelblue', size = 2) + geom_point() + xlab('') + ylab('均价')
  38. p
  39. # 房屋建筑时间确实严重,我们按区域分组,使用众数填充
  40. house$建筑时间[house$建筑时间 == ''] <- NA
  41. # 自定义众数函数
  42. stat.mode <- function(x, rm.na = TRUE){
  43. if (rm.na == TRUE){
  44. y = x[!is.na(x)]
  45. }
  46. res = names(table(y))[which.max(table(y))]
  47. return(res)
  48. }
  49. # 自定义函数,实现分组替补
  50. my.impute <- function(data, category.col = NULL,
  51. miss.col = NULL, method = stat.mode){
  52. impute.data = NULL
  53. for(i in as.character(unique(data[,category.col]))){
  54. sub.data = subset(data, data[,category.col] == i)
  55. sub.data[,miss.col] = impute(sub.data[,miss.col], method)
  56. impute.data = c(impute.data, sub.data[,miss.col])
  57. }
  58. data[,miss.col] = impute.data
  59. return(data)
  60. }
  61. final_house <- subset(my.impute(house, '区域', '建筑时间'),select = c(区域,type.new,floow,面积,价格.W.,单价.平方米.,建筑时间))
  62. final_house <- transform(final_house, builtdate2now = 2016-as.integer(substring(as.character(建筑时间),1,4)))
  63. final_house <- subset(final_house, select = -建筑时间)
  64. # 使用k-means聚类,探究上海的各个区域可以划分为几类
  65. # 自定义函数
  66. tot.wssplot <- function(data, nc, seed=1234){
  67. #假设分为一组时的总的离差平方和
  68. tot.wss <- (nrow(data)-1)*sum(apply(data,2,var))
  69. for (i in 2:nc){
  70. #必须指定随机种子数
  71. set.seed(seed)
  72. tot.wss[i] <- kmeans(data, centers=i, iter.max = 100)$tot.withinss
  73. }
  74. plot(1:nc, tot.wss, type="b", xlab="Number of Clusters",
  75. ylab="Within groups sum of squares",col = 'blue',
  76. lwd = 2, main = 'Choose best Clusters')
  77. }
  78. standrad <- data.frame(scale(final_house[,c('面积','价格.W.','单价.平方米.')]))
  79. myplot <- tot.wssplot(standrad, nc = 15)
  80. # 根据图形,大致可以将数据聚为5类
  81. set.seed(1234)
  82. clust <- kmeans(x = standrad, centers = 5, iter.max = 100)
  83. table(clust$cluster)
  84. # 按聚类的结果,比较各类中房子的平均面积、价格和单价
  85. aggregate(final_house[,3:5], list(clust$cluster), mean)
  86. # 按照聚类的结果,查看各类中的区域分布
  87. table(house$区域,clust$cluster)
  88. # 各户型的平均面积
  89. aggregate(final_house$面积, list(final_house$type.new), mean)
  90. # 绘制面积与单价的散点图,并按聚类进行划分
  91. p <- ggplot(data = final_house[,3:5], mapping = aes(x = 面积,y = 单价.平方米., color = factor(clust$cluster)))
  92. p <- p + geom_point(pch = 20, size = 3)
  93. p + scale_colour_manual(values = c("red","blue", "green", "black", "orange"))
  94. # 构造楼层和聚类结果的哑变量
  95. # 将几个离散变量转换为因子,目的便于下面一次性处理哑变量
  96. final_house$cluster <- factor(clust$cluster)
  97. final_house$floow <- factor(final_house$floow)
  98. final_house$type.new <- factor(final_house$type.new)
  99. # 筛选出所有因子型变量
  100. factors <- names(final_house)[sapply(final_house, class) == 'factor']
  101. # 将因子型变量转换成公式formula的右半边形式
  102. formula <- f <- as.formula(paste('~', paste(factors, collapse = '+')))
  103. dummy <- dummyVars(formula = formula, data = final_house)
  104. pred <- predict(dummy, newdata = final_house)
  105. head(pred)
  106. # 将哑变量规整到final_house数据集中
  107. final_house2 <- cbind(final_house,pred)
  108. # 筛选出需要建模的数据
  109. model.data <- subset(final_house2,select = -c(1,2,3,8,17,18,24))
  110. # 直接对数据进行线性回归建模
  111. fit1 <- lm(价格.W. ~ .,data = model.data)
  112. summary(fit1)
  113. library(car)
  114. # Box-Cox转换
  115. powerTransform(fit1)
  116. fit2 <- lm(log(价格.W.) ~ .,data = model.data)
  117. # 使用plot方法完成模型定性的诊断
  118. opar <- par(no.readonly = TRUE)
  119. par(mfrow = c(2,2))
  120. plot(fit2)
  121. par(opar)