发布于2021-07-25 07:13 阅读(1001) 评论(0) 点赞(11) 收藏(5)
项目来源:
https://www.kaggle.com/anthonypino/melbourne-housing-market
项目简介:
利用以往的房屋销售信息,分析哪种房屋最值得推荐给投资者进行投资。
PS: 本次项目是在jupyter上运行的。
导入模块:
%matplotlib inline
import pandas as pd
import seaborn as sns
import statsmodels.formula.api as smf
from sklearn.linear_model import LinearRegression
from sklearn import metrics
from sklearn.model_selection import train_test_split
import numpy as np
from scipy.stats import norm # for scientific Computing
from scipy import stats, integrate
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置汉字字体,优先使用黑体
plt.rcParams['font.size'] = 12 # 设置字体大小
plt.rcParams['axes.unicode_minus'] = False # 设置正常显示负号
加载数据:
melbourne_data = pd.read_csv("./Melbourne_housing_FULL.csv")
melbourne_data.head(10)
接下来正式开始进行分析啦!
melbourne_data.shape
melbourne_data.info()
从上面的数据信息可以看出,非数值数据被视为对象。该列表包括以下列:“suburban”、“Address”、“Type”、“Method”、“SellerG”、“Date”、“councileArea”、“Regionname”。在接下来的几个步骤中,我们将把对象数据类型更改为category和Date数据类型。
# 验证字符串类型的数据
melbourne_data.select_dtypes(["object"]).columns
# 将所有字符串数据类型更改为类别-此步骤对于能够绘制类别数据以进行分析是必需的
objdtype_cols = melbourne_data.select_dtypes(["object"]).columns
melbourne_data[objdtype_cols] = melbourne_data[objdtype_cols].astype('category')
melbourne_data.info()
## 看上面的数据信息,我们可以注意到“数据”也被转换成了类别。
## 在这一步中,我们将将日期转换为datetime
melbourne_data['Date'] = pd.to_datetime( melbourne_data['Date'])
melbourne_data.info()
在接下来的几个步骤中,我们将对数值特征变量进行数据预处理。
melbourne_data.describe().T
观察以上有关数字数据的信息,可以注意到邮政编码也被视为数字数据。既然我们知道邮政编码是一个分类数据,我们将把它分类。
melbourne_data["Postcode"] = melbourne_data["Postcode"].astype('category')
melbourne_data.describe().T
仔细评估数据后,可以注意到变量“Rooms”和“Bedroom2”非常相似,应该删除其中一列以避免重复数据。
## 在这一步中,我们将首先通过观察“Rooms”和“Bedroom2”来确认我们的上述声明
melbourne_data['b 2 r'] = melbourne_data["Bedroom2"] - melbourne_data["Rooms"]
melbourne_data[['b 2 r', 'Bedroom2', 'Rooms']].head()
## 我们可以看到,这里的差别非常小,删除这两列中的一列是明智的
melbourne_data = melbourne_data.drop(['b 2 r', 'Bedroom2'], 1)
我们可以使用多种方法来探索缺失的数据。在这里,我们将首先使用一个可视化的方式来获得一些提示。在后面的步骤中,我们将进行一些计算,以获得每个变量中丢失数据的确切数量。根据数据、我们的经验和业务需要,我们要么填写缺失的值,要么删除具有空值的行或列。
## 可视化缺失值
fig, ax = plt.subplots(figsize=(15,7))
sns.heatmap(melbourne_data.isnull(), yticklabels=False,cmap='viridis')
从上图可以得出结论,price,bathroom,car和landsize,lattitude和longtitude有部分缺失值,在buildingarea和bulityear中有许多缺少的值。在下一步中,让我们研究缺失值的计数。
# 百分比缺失值
melbourne_data.isnull().sum()/len(melbourne_data)*100
从上面的信息中,我们可以注意到很少的特性变量仍然有很大比例的缺失值。此时我们将忽略它,但在稍后的状态中,如果我们将这些作为后续的特征变量,我们将探索填充这些信息或从数据中删除这些信息的方法。
melbourne_data = melbourne_data.drop(["Landsize", "BuildingArea", "YearBuilt"], axis=1)
##另外,因为我们的目标变量是price,所以在缺少price值时,删除price列的行是有意义的
melbourne_data.dropna(subset=["Price"], inplace=True)
melbourne_data['Car']=melbourne_data['Car'].fillna(melbourne_data['Car'].mode()[0])
melbourne_data['Bathroom']=melbourne_data['Bathroom'].fillna(melbourne_data['Bathroom'].mode()[0])
melbourne_data.shape
# 百分比缺失值
melbourne_data.isnull().sum()/len(melbourne_data)*100
异常值可以显著影响数据分析,也可以影响数据的规范化。在数据预处理过程中,识别和删除它们是非常重要的。在接下来的几个步骤中,我们将在数据中处理异常值(如果有的话)。
melbourne_data.describe().T
从上面的统计总结中我们可以看到,我们数据中的最高价格接近1120万美元。这看起来像是一个明显的异常值。但是在删除它之前,让我们首先确保在这个范围内只有很少的值。
##为了找出异常值,我们将数据划分为不同的价格范围,以确定不同价格范围内数据出现的次数
melbourne_data['PriceRange'] = np.where(melbourne_data['Price'] <= 100000, '0-100,000',
np.where ((melbourne_data['Price'] > 100000) & (melbourne_data['Price'] <= 1000000), '100,001 - 1M',
np.where((melbourne_data['Price'] > 1000000) & (melbourne_data['Price'] <= 3000000), '1M - 3M',
np.where((melbourne_data['Price']>3000000) & (melbourne_data['Price']<=5000000), '3M - 5M',
np.where((melbourne_data['Price']>5000000) & (melbourne_data['Price']<=6000000), '5M - 6M',
np.where((melbourne_data['Price']>6000000) & (melbourne_data['Price']<=7000000), '6M - 7M',
np.where((melbourne_data['Price']>7000000) & (melbourne_data['Price']<=8000000), '7M-8M',
np.where((melbourne_data['Price']>8000000) & (melbourne_data['Price']<=9000000), '8M-9M',
np.where((melbourne_data['Price']>9000000) & (melbourne_data['Price']<=10000000), '9M-10M',
np.where((melbourne_data['Price']>10000000) & (melbourne_data['Price']<=11000000), '10M-11M',
np.where((melbourne_data['Price']>11000000) & (melbourne_data['Price']<=12000000), '11M-12M', '')
))))))))))
melbourne_data.groupby(['PriceRange']).agg({'PriceRange': ['count']})
通过研究上表,可以得出以下结论:
为了本研究的目的,让我们删除符合上述条件的行。
melbourne_data.info()
melbourne_data.describe().T
melbourne_data.drop(melbourne_data[(melbourne_data['PriceRange'] == '0-100,000') |
(melbourne_data['PriceRange'] == '7M-8M') |
(melbourne_data['PriceRange'] == '8M-9M') |
(melbourne_data['PriceRange'] == '11M-12M')].index, inplace=True)
melbourne_data.describe().T
melbourne_data.groupby(['Rooms'])['Rooms'].count()
melbourne_data.drop(melbourne_data[(melbourne_data['Rooms'] == 12) |
(melbourne_data['Rooms'] == 16)].index, inplace=True)
melbourne_data.describe().T
##sns.distplot(melbourne_data, kde=False, bins=20).set(xlabel='Price');
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
##melbourne_data.select_dtypes(include = numerics)
melbourne_data.select_dtypes(include = numerics).hist(bins=15, figsize=(15, 6), layout=(2, 4))
melbourne_data['Distance'] = round(melbourne_data['Distance'])
melbourne_data.shape
## 从日期中提取年出来
melbourne_data['Year']=melbourne_data['Date'].apply(lambda x:x.year)
melbourne_data.head(5)
#data subset by type
#house price
melbourne_data_h=melbourne_data[melbourne_data['Type']=='h']
#condo price
melbourne_data_u=melbourne_data[melbourne_data['Type']=='u']
#townhouse price
melbourne_data_t=melbourne_data[melbourne_data['Type']=='t']
#house,condo and townhouse price groupby year and mean
melbourne_data_h_y=melbourne_data_h.groupby('Year').mean()
melbourne_data_u_y=melbourne_data_u.groupby('Year').mean()
melbourne_data_t_y=melbourne_data_t.groupby('Year').mean()
melbourne_data_h_y.head()
#sns.lmplot(x="Year", y="Price", hue="Type", data=melbourne_data, x_estimator=np.mean);
melbourne_data_h_y['Price'].plot(kind='line', color='r',label='House')
melbourne_data_u_y['Price'].plot(kind='line', color='g',label='Condo')
melbourne_data_t_y['Price'].plot(kind='line', color='b',label='Townhouse')
year_xticks=[2016,2017,2018]
plt.ylabel('Price')
plt.xticks(year_xticks)
plt.title('每种类型的房子价格年趋势')
plt.legend()
House大幅下跌10万套,Condo价格缓慢攀升,而Townhouse价格保持稳定。从这张图上可以看出,预计House会下降,但坡度较小的Townhouse房价会下降,不变的Condo价格会上升。对开发商来说,是时候在2019年建更多的公寓了。购房者的住房预算需要削减,是时候在2019年买房了。
melbourne_data.shape
melbourne_data.columns
melbourne_data_South_M=melbourne_data[melbourne_data['Regionname']=='Southern Metropolitan']
melbourne_data_South_M_average=melbourne_data_South_M.groupby(['Year'])['Price'].mean()
# create X and y
X = melbourne_data_South_M[[ 'Year']]
y = melbourne_data_South_M[['Price']]
# instantiate and fit
lm2 = LinearRegression()
lm2.fit(X, y)
# print the coefficients
lm2.intercept_
lm2.coef_
X_new = pd.DataFrame({'Year': [2019,2020,2021]})
lm2.predict(X_new)
根据这一粗略估算,2019年和2020年墨尔本房屋平均价格将为1557639、1630019。
melbourne_data_SM=melbourne_data[melbourne_data['Regionname']=='Southern Metropolitan']
melbourne_data_SM_u=melbourne_data_SM[melbourne_data_SM['Type']=='u']
melbourne_data_SM_u.shape
lm1 = smf.ols(formula='Price ~ Year', data=melbourne_data_SM_u).fit()
lm1.params
X_new = pd.DataFrame({'Year': [2016,2017,2018,2019,2020,2021]})
lm1.predict(X_new)
# 拟合度
lm1.rsquared
这拟合度,看看就得了。
melbourne_data_E=melbourne_data[melbourne_data['Regionname']=='Eastern Metropolitan']
melbourne_data_E_u=melbourne_data_E[melbourne_data_E['Type']=='u']
lme = smf.ols(formula='Price ~ Year', data=melbourne_data_E_u).fit()
# print the coefficients
lme.params
melbourne_data_E_u.shape
X_new = pd.DataFrame({'Year': [2016,2017,2018,2019,2020,2021]})
# predict for a new observation
lme.predict(X_new)
对于Eastern Metropolitan,预计2016年至2017年价格将增长10%,2018年至2019年价格将增长7.7%。虽然和南部地区相比,这个数字要少一些。
melbourne_data['Month']=pd.DatetimeIndex(melbourne_data['Date']).month
melbourne_data_2016=melbourne_data[melbourne_data['Year']==2016]
melbourne_data_2017=melbourne_data[melbourne_data['Year']==2017]
melbourne_data_2018=melbourne_data[melbourne_data['Year']==2018]
melbourne_data_2016_count=melbourne_data_2016.groupby(['Month']).count()
melbourne_data_2017_count=melbourne_data_2017.groupby(['Month']).count()
melbourne_data_2018_count=melbourne_data_2018.groupby(['Month']).count()
Comparison={2016:melbourne_data_2016.shape,2017:melbourne_data_2017.shape,2018:melbourne_data_2018.shape}
Comparison
label_2016=['January','March','April','May','June','July','August','September','October','November','December']
plt.pie(melbourne_data_2016_count['Price'],labels=label_2016,autopct='%.1f %%')
plt.title('Year 2016')
plt.show()
label_2017=['January','February','March','April','May','June','July','August','September','October','November','December']
plt.pie(melbourne_data_2017_count['Price'],labels=label_2017,autopct='%.1f %%')
plt.title('Year 2017')
label_2018=['January','February','March','June','October']
plt.pie(melbourne_data_2018_count['Price'],labels=label_2018,autopct='%.1f %%')
plt.title('Year 2018')
总的来说,2016年和2017年的冬季似乎销量最少。这意味着从5月到11月房屋销售将有更多优惠。2018年的数据缺失较多,与其他年份相比只有三分之一左右,因此很难得出结论。
# 取个短一点的名字
melbourne_data['Regionabb'] = melbourne_data['Regionname'].map({'Northern Metropolitan':'N Metro',
'Western Metropolitan':'W Metro',
'Southern Metropolitan':'S Metro',
'Eastern Metropolitan':'E Metro',
'South-Eastern Metropolitan':'SE Metro',
'Northern Victoria':'N Vic',
'Eastern Victoria':'E Vic',
'Western Victoria':'W Vic'})
总的来说,东、北、南和西Metropolitan都是受欢迎的地区。 接下来看看每种类型的地区价格。
sns.lmplot(x="Year", y="Price",hue="Type", data=melbourne_data,col='Regionabb', x_estimator=np.mean,col_wrap=2)
plt.ylim(200000, 2000000)
plt.xlim(2015,2020)
sns.lmplot(x="Year", y="Price",hue="Type", data=melbourne_data[melbourne_data['Regionabb']=='S Metro'], x_estimator=np.mean);
总体而言, Townhouse in E Metro, Condo in East Metro, House in S Metro, Condo in S Metro and Condo in N Metro每年都在增长。
melbourne_data_S=melbourne_data[melbourne_data['Regionabb']=='S Metro']
sns.lmplot(x="Year", y="Price", data=melbourne_data_S[melbourne_data_S['Type']=='u'], x_estimator=np.mean)
Pct_change=melbourne_data.groupby(['Year','Regionabb','Type'],as_index=False)['Price'].mean()
Pct_change = Pct_change.sort_values(['Regionabb', 'Type','Year']).set_index(np.arange(len(Pct_change.index)))
Pct_change.info()
melbourne_data_count_region_y=melbourne_data.groupby(['Year','Regionabb','Type'],as_index=False)['Price'].count()
melbourne_data_count_region_y = melbourne_data_count_region_y.sort_values(['Regionabb', 'Type','Year']).set_index(np.arange(len(melbourne_data_count_region_y.index)))
melbourne_data_count_region_y.rename(columns={'Price':'Count'}, inplace=True)
def PCTM(gg):
df=pd.DataFrame(gg['Price'].pct_change())
df['Year']=gg['Year']
df['region']=gg['Regionabb']
df['Type']=gg['Type']
df=df[df['Year']!=2016]
return df
melboune_growthrate_y_t=PCTM(Pct_change)
melboune_growthrate_y_t1=melboune_growthrate_y_t[melboune_growthrate_y_t['region'].isin(['N Metro','S Metro','E Metro','SE Metro','W Metro','S Metro'])]
melboune_growthrate_y_t1.rename(columns={'Price':'Price Growth Rate'}, inplace=True)
melboune_growthrate_y_t1[melboune_growthrate_y_t1['Price Growth Rate']>0.05]
由于2018年大量数据缺失,S Metro的condo在2017年和2018年分别为8.7%和2.7%。如果选择2017年来看价格的增长,E Metro、SE Metro和S Metro的condo和townhouse、W Metro的townhouse和S Metro的house均呈现超过5%的正增长。展望2018年,人们似乎转向在SE、E Metro或者S Metro购买更多。
Sales_count=melbourne_data.groupby(['Regionabb','Type'])['Price'].count()
Sales_count.nlargest(20)
def PCTMC(gg):
df=pd.DataFrame(gg['Count'].pct_change())
df['Year']=gg['Year']
df['region']=gg['Regionabb']
df['Type']=gg['Type']
df=df[df['Year']!=2016]
return df
melboune_growthrate_y_c=PCTMC(melbourne_data_count_region_y)
melboune_growthrate_y_c1=melboune_growthrate_y_c[melboune_growthrate_y_c['region'].isin(['N Metro','S Metro','E Metro','SE Metro','W Metro','S Metro'])]
melboune_growthrate_y_c1.rename(columns={'Count':'Count Growth Rate'}, inplace=True)
melboune_growthrate_y_c1[melboune_growthrate_y_c1['Count Growth Rate']>0.2]
melboune_count1=melbourne_data_count_region_y[melbourne_data_count_region_y['Regionabb'].isin(['S Metro','E Metro','SE Metro','W Metro','S Metro','N Metro'])]
melboune_count1[melboune_count1['Count']>1000]
从以上信息统计的增长百分比和实际销售额按年度计算,S Metro和N Metro似乎是人们倾向于支付更多,购买更多的地区,但随着价格不断上涨,那些住在南部的试图转移到E Metro和SE Metro。
本节结论: 1.house方面,S Metro 2017年价格增长5%以上,三年销售4718套,排名第二;Condo方面,S Metro 2017年销售2782套,排名第四,价格增长8.7%。 2.E Metro和SE Metro的condo和townhouse潜力很大,现在没有S Metro那么吸引人。他们的数量增长率超过100%,价格增长率超过8%。
sns.boxplot(x = 'Method', y = 'Price', data = melbourne_data)
plt.show()
# 销售方式不影响价格
sns.lmplot(x="Year", y="Price", hue="Rooms", data=melbourne_data, x_estimator=np.mean)
# impact on Prcie VS Year
结论:离城中心越远,价格越低。
sns.lmplot(x="Distance", y="Price", data=melbourne_data, x_estimator=np.mean);
sns.lmplot(x="Car", y="Price", data=melbourne_data, x_estimator=np.mean)
# 车位越多,价格越贵
找出最理想的房子类型。
Ideal_House=melbourne_data.groupby(['Regionabb','Type','Rooms','Bathroom'])['Price'].count()
Ideal_House.loc[['S Metro'],'h'].nlargest(10)
结论:在S Metro,3房1卫或2卫的房子和4房2卫的房子销量最大。
Ideal_House.nlargest(10)
结论:其中,N Metro房最受欢迎,W Metro紧随其后。一般来说,house比其他类型的好。拥有两间卧室和一间浴室的S Metro的condo被列为销量前三名。
Ideal_House.loc[['E Metro'],'u'].nlargest(10)
E Metro区最好的公寓类型是两室一厅。
corrmat=melbourne_data.corr()
fig,ax=plt.subplots(figsize=(12,10))
sns.heatmap(corrmat,annot=True,annot_kws={'size': 12})
与其他因素相比,rooms和bathroom与price的相关性最高。
另外为方便需要的朋友运行代码,我也把完整的代码和数据文件放到了网盘上,需要的朋友自取。
链接:https://pan.baidu.com/s/1qw-fwmykg6-G3RmLBKUT7A
提取码:1024
原文链接:https://blog.csdn.net/qq_44186838/article/details/119043335
作者:机甲战士
链接:http://www.pythonpdf.com/blog/article/469/a8643144571c42a4695b/
来源:编程知识网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!