本站消息

  出租广告位,需要合作请联系站长

  今日名言-想象你自己对困难作出的反应,不是逃避或绕开它们,而是面对它们,同它们打交道,以一种进取的和明智的方式同它们奋斗 。——马克斯威尔·马尔兹

  今日名言-用谅解、宽恕的目光和心理看人、待人。人就会觉得葱笼的世界里,春意盎然,到处充满温暖。——蔡文甫


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

基于pandas、matplotlib和seaborn进行数据分析实战【超详细讲解】

发布于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)

在这里插入图片描述
接下来正式开始进行分析啦!

1 数据探索与数据清洗

1.1 数据探索

melbourne_data.shape

在这里插入图片描述

melbourne_data.info()

在这里插入图片描述
从上面的数据信息可以看出,非数值数据被视为对象。该列表包括以下列:“suburban”、“Address”、“Type”、“Method”、“SellerG”、“Date”、“councileArea”、“Regionname”。在接下来的几个步骤中,我们将把对象数据类型更改为category和Date数据类型。

# 验证字符串类型的数据
melbourne_data.select_dtypes(["object"]).columns

在这里插入图片描述

1.2 更换数据类型

# 将所有字符串数据类型更改为类别-此步骤对于能够绘制类别数据以进行分析是必需的
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)

1.3 缺失值处理

我们可以使用多种方法来探索缺失的数据。在这里,我们将首先使用一个可视化的方式来获得一些提示。在后面的步骤中,我们将进行一些计算,以获得每个变量中丢失数据的确切数量。根据数据、我们的经验和业务需要,我们要么填写缺失的值,要么删除具有空值的行或列。

## 可视化缺失值
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

在这里插入图片描述

1.4 寻找异常数据

异常值可以显著影响数据分析,也可以影响数据的规范化。在数据预处理过程中,识别和删除它们是非常重要的。在接下来的几个步骤中,我们将在数据中处理异常值(如果有的话)。

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']})

在这里插入图片描述
通过研究上表,可以得出以下结论:

  • 1个数据项,范围0-100,00
  • 7M-8M范围内有2个数据
  • 8M-9M范围内有1个数据
  • 11M-12M范围内有1个数据,

为了本研究的目的,让我们删除符合上述条件的行。

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

在这里插入图片描述

2 数据呈现与关系

2.1 我们考虑的第一个因素是价格与年份和季节的关系。然后利用线性函数预测2019年和2020年的价格。

2.1.1 每种类型的房子价格年趋势

## 从日期中提取年出来
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年买房了。

2.2 预测2019年和2020年Southern Metropolitan所有类型的房屋、Southern Metropolitan的Condo和Eastern Metropolitan的Condo价格

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。

2.2.1 Southern Metropolitan的Condo价格预测

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

在这里插入图片描述
这拟合度,看看就得了。

2.2.2 Eastern Metropolitan的Condo价格预测

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%。虽然和南部地区相比,这个数字要少一些。

2.3 Seasonal performance

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年的数据缺失较多,与其他年份相比只有三分之一左右,因此很难得出结论。

2.4 Region versus Price

# 取个短一点的名字
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'})

2.4.1每种类型的地区价格变化与年份

总的来说,东、北、南和西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)

在这里插入图片描述

2.4.2 特征工程,以获得每个地区和类型的年数量增长率和价格增长率

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

2.4.2.1 每个地区和类型的价格增长率超过5%

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购买更多。

2.4.2.2 按类型划分,数量最多的20个地区

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

2.4.2.3 每个地区和类型的计数增长率超过20%

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]

在这里插入图片描述

2.4.2.4 按年份地区和类型划分,实际计数超过1000

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%。

2.5 其他数值特征与价格间的关系

2.5.1 Method vs Price

sns.boxplot(x = 'Method', y = 'Price', data = melbourne_data)
plt.show()
# 销售方式不影响价格

在这里插入图片描述

2.5.2 Rooms

sns.lmplot(x="Year", y="Price", hue="Rooms", data=melbourne_data,  x_estimator=np.mean)
# impact on Prcie VS Year

在这里插入图片描述

2.5.3 Distance vs Price

结论:离城中心越远,价格越低。

sns.lmplot(x="Distance", y="Price", data=melbourne_data, x_estimator=np.mean);

在这里插入图片描述

2.5.4 Car spot vs Price

sns.lmplot(x="Car", y="Price", data=melbourne_data, x_estimator=np.mean)
# 车位越多,价格越贵

在这里插入图片描述

2.6 Ideal house type

找出最理想的房子类型。

2.6.1 在S Metro,按类型、rooms、bathroom统计排名前10的房子类型

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卫的房子销量最大。

2.6.2 按类型、rooms、bathroom统计排名前10的房子类型

Ideal_House.nlargest(10)

在这里插入图片描述
结论:其中,N Metro房最受欢迎,W Metro紧随其后。一般来说,house比其他类型的好。拥有两间卧室和一间浴室的S Metro的condo被列为销量前三名。

2.6.3 在E Metro的condo中,按类型、rooms、bathroom统计排名前10的房子类型

Ideal_House.loc[['E Metro'],'u'].nlargest(10)

在这里插入图片描述
E Metro区最好的公寓类型是两室一厅。

2.7 关系热图

corrmat=melbourne_data.corr()

fig,ax=plt.subplots(figsize=(12,10))
sns.heatmap(corrmat,annot=True,annot_kws={'size': 12})

在这里插入图片描述
与其他因素相比,rooms和bathroom与price的相关性最高。

3 最终结论

  • 从2.1.1可以得出:house一般会下降,condo价格会上升。这意味着投资公寓会更好。
  • 从2.4得出:在hous方面,S Metro 2017年价格增长超过5%,三年销售4718套,排名第二;在condo方面,S Metro 2017年销售2782套,排名第四,价格增长8.7%。
  • 从2.4得出:E Metro和SE Metro的condo和townhouse潜力很大,现在没有S Metro那么吸引人。增长率超过100%,价格增长率超过8%。
  • 从2.6得出,南方地铁的condo排在第三位。虽然N Metro和W Metro的house数量最多,但它们的价格正在下降,如第2.4节sns.lmplot所示。从数量上看,S Metro的condo具有巨大的市场潜力,因为其数量排名第三,价格在第2.4节中呈现出逐年上升的趋势。S Metro的house也有很大的市场,但增长率不如condo。
  • 最后在结合理想户型,2rooms1bathroom的S Metro的condo将被推荐给投资者或开发商。

另外为方便需要的朋友运行代码,我也把完整的代码和数据文件放到了网盘上,需要的朋友自取。
链接: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/

来源:编程知识网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

11 0
收藏该文
已收藏

评论内容:(最多支持255个字符)