第二篇數(shù)據(jù)分析項目的實戰(zhàn),為更好的復習鞏固已學知識,話不多說悠栓,進入正題。
分析思路
1.數(shù)據(jù)的清理
導入常用包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei'] #顯示中文
導入數(shù)據(jù)并讀取前5行
df = pd.read_csv("鏈家二手房.csv", engine = 'python')
df.head()
因為數(shù)據(jù)列名為中文字符按价,所有轉(zhuǎn)換為英文字符便于后續(xù)處理惭适。
df.rename(columns = {'小區(qū)名稱': 'village', '戶型': 'house_type',
'面積': 'area', '區(qū)域': 'district', '朝向': 'orientations', '價格(W)': 'total_price',
'單價(平方米)': 'unit_price', '建筑時間': 'construction_time', '樓層': 'floor'}, inplace = True)
df.head()
查看數(shù)據(jù)類型和缺失值
df.dtypes
df.isnull().sum()
- orientations字段缺失行數(shù)1355,construction_time字段缺失行數(shù)6216楼镐,
- 這些缺失值在下面對其進行分析時再加以處理
通過以上數(shù)據(jù)預覽發(fā)現(xiàn)癞志,floor列的數(shù)據(jù)含有兩層含義,故而將其分成兩列便于后續(xù)的使用
df1 = pd.concat([df,df['floor'].str.split('/', expand = True)], axis = 1)
df1.head()
- split是分隔符框产,concat兩表的聯(lián)結(jié)凄杯,axis = 1 按列維度合并
刪除floor列,重新命名新的列名
# 重命名得到的兩列
del df1['floor']
df1.rename(columns = {0: 'floor_level', 1: 'floor'}, inplace = True)
df1.tail()
提取construction_time和floor列下字段的數(shù)字部分
df1['construction_time'] = df1['construction_time'].str.extract('(\d+)年建') #刪除字段文字部分茅信,保留數(shù)字
df1['floor'] = df1['floor'].str.extract('(\d+)層')
df1.head()
再查看數(shù)據(jù)類型
df1.info()
- construction_time和floor是字符串格式盾舌,需轉(zhuǎn)化為浮點數(shù)格式
df1['construction_time'] = df1['construction_time'].astype(float)
df1['floor'] = df1['floor'].astype(float)
df1.dtypes
查看描述性統(tǒng)計
df1.describe() #查看描述性統(tǒng)計
- 由以上描述性統(tǒng)計結(jié)果可以得到如下信息:
·1.面積平均值為96㎡贮泞,面積中位數(shù)為85㎡奔滑,說明少數(shù)大面積房源拉高了總體平均水平
·2.總價平均值為580萬,總價中位數(shù)為430萬酵熙,情況同上酌摇,少數(shù)總價高的房源拉高了總體平均水平
·3.單價平均值為59725元膝舅,單價中位數(shù)為58068元,平均值與中位數(shù)基本相等窑多,說明房價升高趨勢比較線性
2.數(shù)據(jù)分析:各區(qū)域房源數(shù)量分布
上海市區(qū)共分為三個等級:
1.黃浦區(qū)仍稀、長寧區(qū);
2.靜安區(qū)埂息、徐匯區(qū)技潘;
3.楊浦區(qū)、虹口區(qū)千康、普陀區(qū)享幽。
上海郊區(qū)共分為三個等級:
1.寶山區(qū)、閔行區(qū)拾弃;
2.松江區(qū)值桩、嘉定區(qū)、青浦區(qū)豪椿;
3.奉賢區(qū)奔坟、崇明區(qū)携栋、金山區(qū)。
district_number = df1.district.value_counts().reset_index().sort_values(by = 'district', ascending = False)
district_number
plt.figure(figsize=(9, 4))
plt.bar(district_number['index'],district_number.district)
plt.title('各城區(qū)房源數(shù)量')
- 由以上柱狀圖可知咳秉,除了靜安區(qū)婉支、崇明區(qū)和金山區(qū)房源數(shù)量不足50套外,其他14個
城區(qū)二手房數(shù)量均在1300套以上滴某,數(shù)量最多的是浦東區(qū)磅摹,共有2599套
3.各城區(qū)總面積與平均面積的分布
3.1各城區(qū)總面積分布
由上圖可知靜安、崇明和金山區(qū)房源數(shù)量很少霎奢,無法代表整體,因此刪除三個區(qū)數(shù)據(jù)
dis_list = list(df1.district.drop_duplicates()) #drop_duplicates()去除確定下列的重復列
dis_list.remove('崇明')
dis_list.remove('金山')
dis_list.remove('靜安')
dis_list
查看清理后數(shù)據(jù)前五行
df2 = df1[df1.district.isin(dis_list)]
df2.head()
接下來計算各城區(qū)二手房源總面積:
grouped_total_area = df2.groupby('district').sum().sort_values('area', ascending = False).reset_index()
grouped_total_area #這里運用groupby進行分組聚合
通過折線圖展示各城區(qū)總面積分布趨勢
plt.figure(figsize = (12, 5))
grouped_total_area.plot(x = 'district', y = 'area', kind = 'line')
plt.title('各城區(qū)總面積分布')
- 如圖所示饼灿,總面積排名前三的是:青浦幕侠、松江和浦東,這得益于它們較大的面積
3.2各城區(qū)平均面積分布
grouped_area = df2.groupby('district').mean().reset_index().sort_values('area', ascending = False)
grouped_area
同上進行可視化
plt.figure(figsize = (9, 5))
grouped_area.plot(x = 'district', y = 'area', kind = 'line')
#plt.plot(grouped_area.district,grouped_area.area)
plt.title('各城區(qū)平均面積分布')
- 以上折線圖所示,青浦區(qū)總面積和平均面積遠遠大于其他城區(qū)面積碍彭,青浦區(qū)共有1769套房源晤硕,數(shù)量較大,不太可能出現(xiàn)異常庇忌,故分析可能原因:不在市中心位置舞箍,建設成本較低,房屋設計面積較大皆疹。
- 各城區(qū)總面積和平均面積趨勢大致一樣疏橄,各城區(qū)平均面積在[77,116]之間,其中面積在[100,116]之間的為松江略就、黃埔和金山捎迫,面積在[90,100)之間的為奉賢、長寧表牢、閔行和靜安窄绒,面積在[80,90)之間的為嘉定、虹口崔兴、崇明彰导、浦東、閘北敲茄、寶山位谋、普陀和徐匯,楊浦區(qū)平均面積在77.8㎡
3.3全市平均面積分布
以區(qū)間[0,50),[50,100),[100,150),[150,200),[200,+∞)為劃分標準折汞,將面積劃分為tinysmall倔幼、
small、medium爽待、big损同、huge五個等級翩腐,分別對應極小戶型、小戶型膏燃、中等戶型茂卦、大戶型和局大戶型。
df2.loc[(df2['area'] >= 0) & (df2['area'] < 50), 'area_level'] = 'tinysmall'
df2.loc[(df2['area'] >= 50) & (df2['area'] < 100), 'area_level'] = 'small'
df2.loc[(df2['area'] >= 100) & (df2['area'] <150), 'area_level'] = 'medium'
df2.loc[(df2['area'] >= 150) & (df2['area'] <200), 'area_level'] = 'big'
df2.loc[(df2['area'] >= 200), 'area_level'] = 'huge'
df2.head()
求出各戶型的數(shù)量:
grouped_area_level = df2.groupby('area_level').total_price.count().reset_index()
grouped_area_level #求各戶型的數(shù)量
為了體現(xiàn)各戶型分布情況组哩,這里用柱狀圖
plt.bar(grouped_area_level.area_level, grouped_area_level.total_price)
plt.title('各戶型數(shù)量分布')
- 由圖上可知:
1.平均面積為small的房源數(shù)量占據(jù)總數(shù)的50%等龙,即一半房源的面積在區(qū)間[50,100)㎡
2.平均面積為medium的房源數(shù)量占據(jù)總數(shù)的25%,即四分之一的房源面積在區(qū)間[100,150)㎡
3.平局面積為tinysmall的房源數(shù)量占據(jù)總數(shù)的17%伶贰,即17%的房源面積在區(qū)間[0,50)㎡
4.數(shù)據(jù)分析:各城區(qū)總價和單價分布
4.1總價分布
# 把分區(qū)后的總價組成一個字典蛛砰,以便下面將它轉(zhuǎn)化為dataframe
good = dict(list(df2.groupby('district')['total_price']))
# 轉(zhuǎn)化為dataframe
gooddf = pd.DataFrame(good)
# 作出總價箱線圖
plt.figure(figsize = (12,5))
gooddf.boxplot()
plt.ylim(0,3000)
plt.title('各城區(qū)總價箱線圖')
各城區(qū)總價平均值排名:
total_price_mean = df2.groupby('district')['total_price'].mean().reset_index().sort_values('total_price')
total_price_mean # 各城區(qū)總價平均值排名
- 由以上結(jié)果可知:
1.總價No.1的為黃浦區(qū),平均值為1059.3萬黍衙,總價區(qū)間跨越大泥畅,總體價格區(qū)間為[500,1300]萬,中位數(shù)小于平均值琅翻,故少數(shù)價格高的拉高總體平均值的現(xiàn)象比較嚴重
2.總價No.2的為長寧區(qū)位仁,平均值為760.8萬,總體價格區(qū)間在為[400方椎,1000]萬聂抢,中位數(shù)接近平均值,總價上升比較線性
3.總價No.3的為徐匯區(qū)棠众,平均值為671.8萬琳疏,總體價格區(qū)間在為[400, 800]萬,中位數(shù)小于平均值摄欲,故少數(shù)價格高的拉高了總體平均值
4.總價No.4的為青浦區(qū)轿亮,平均值為676.0萬,總體價格區(qū)間在為[300胸墙,750]萬我注,中位數(shù)遠小于平均值,故少數(shù)價格高的拉高了總體平均值的現(xiàn)象比較嚴重
4.2平均總價分布
df2.total_price.hist(bins = 20)
plt.title('平均總價分布圖')
- 房屋總價是一個左凸的直方圖迟隅,90%的數(shù)據(jù)集中在[500,1000]的區(qū)間但骨,即90%的房源總價在500萬到1000萬之間,只有約10%的房源屬于極高的價格智袭,這個結(jié)果符合現(xiàn)實房價分布
4.3 各城區(qū)單價分布
good1 = dict(list(df2.groupby('district')['unit_price']))
good1df = pd.DataFrame(good1)
plt.figure(figsize = (12, 5))
good1df.boxplot()
plt.ylim(0,150000)
plt.title('各城區(qū)單價分布箱線圖')
各城區(qū)單價排名:
unit_price_mean = df2.groupby('district')['district', 'unit_price'].mean().reset_index().sort_values('unit_price',ascending = False)
unit_price_mean
- 由以上結(jié)果可知:
①單價No.1的是黃浦奔缠,平均值為90666元,大體價格區(qū)間在[78000,100000]元
②單價No.2的是徐匯吼野,平均值為79156元校哎,大體價格區(qū)間在[69111,90000]元
③單價No.3的是長寧,平均值為75081元,大體價格區(qū)間在[66000,84000]元
全市單價分布:
df2.unit_price.hist(bins = 20)
plt.title('全市單價分布直方圖')
- 單價直方圖接近正態(tài)分布闷哆,該圖所示70%的單價集中在區(qū)間[30000,90000]元腰奋,符合房價的現(xiàn)實分布規(guī)律
4.4總價和單價排名前十的小區(qū)
對小區(qū)進行分組,計算出各小區(qū)房源數(shù)量抱怔,并按照房源數(shù)量降序的順序排序
df3 = df2.groupby('village').total_price.count().reset_index().sort_values('total_price', ascending = False)
df3.head()
- 因為很多小區(qū)房源數(shù)量太少劣坊,其統(tǒng)計值不具有代表性,所以過濾掉房源數(shù)量小于20的小區(qū)
df4 = df3[df3.total_price > 20]
df4.head(10)
然后再把房源數(shù)量大于20的數(shù)據(jù)提取出來
df5 = df2[df2.village.isin(df4.village)]
df5.head()
4.5計算總價排名前15的小區(qū)
對小區(qū)進行分組屈留,計算出各小區(qū)房源數(shù)量局冰,并按照房源數(shù)量降序的順序排序
totalp_village = df5.groupby('village').total_price.mean().sort_values(ascending = False).reset_index().head(15)
totalp_village
展示排名前15小區(qū)的平局總價柱狀圖:
plt.figure(figsize=(20,4))
plt.bar(totalp_village.village,totalp_village.total_price)
plt.title('平均總價排名前15的小區(qū)')
- 總價排名前15的小區(qū)如圖所示,第一名是翠湖天地御苑灌危,平均總價超過了4000萬康二,是第二名尚海灣豪庭的兩倍,經(jīng)查詢了解到乍狐,該小區(qū)位于上海市心臟地帶赠摇,真是朱甍碧瓦
4.6計算單價排名前十五的小區(qū)
totalp_village1 = df5.groupby('village').unit_price.mean().sort_values(ascending = False).head(15).reset_index()
totalp_village1
展示排名前15小區(qū)單價柱狀圖
plt.figure(figsize = (20,5))
plt.bar(totalp_village1.village,totalp_village1.unit_price)
plt.title('平均單價排名前15的小區(qū)')
- 由上圖可知,排名前三位的小區(qū)分別是翠湖天地御苑浅蚪、東方曼哈頓和融創(chuàng)濱江壹號院,
翠湖天地御苑的平均單價最高烫罩,超過了150000元惜傲,高于排名第二的東方曼哈頓近40000元
5.房價與戶型、樓層贝攒、朝向盗誊、建筑年代的關(guān)系
5.1房價與戶型的關(guān)系
按戶型進行分組,計算出每個戶型的房源數(shù)量隘弊,過濾掉房源數(shù)量小于100的戶型
grouped_house_type = df2.groupby('house_type').total_price.count().sort_values(ascending = False).reset_index()
grouped_house_type2 = grouped_house_type.loc[grouped_house_type.total_price>100]
grouped_house_type2
plt.figure(figsize = (10, 5))
plt.bar(grouped_house_type2.house_type,grouped_house_type2.total_price)
plt.title('各戶型數(shù)量柱狀圖')
戶型與房屋均價的柱狀圖
df6 = df2[df2.house_type.isin(grouped_house_type2.house_type)]
df6.head()
grouped_house_type3 = df6.groupby('house_type').unit_price.mean().sort_values(ascending = False).reset_index()
grouped_house_type3
plt.figure(figsize=(15,5))
plt.bar(grouped_house_type3.house_type,grouped_house_type3.unit_price)
plt.title('戶型-房屋均價圖')
- 如圖所示哈踱,單價排名前三的戶型分別是1室2廳、2室0廳梨熙、1室0廳开镣;可以看出,小戶型的房屋比較受歡迎咽扇,因為其總價比較低邪财,經(jīng)濟壓力較小,故而成為熱門戶型质欲,這也導致了這些戶型的價格上漲树埠,使得小戶型的房屋單價高于大戶型的房屋。
5.2 房價與樓層的關(guān)系
計算各個樓層等級的房源數(shù)量嘶伟,注意這里是按照地區(qū)高中低區(qū)劃分的怎憋,并不是按照floor劃分的
a_list = ['高區(qū)','中區(qū)', '低區(qū)']
df7 = df2[df2.floor_level.isin(a_list)]
grouped_floor_level = df7.groupby('floor_level').unit_price.count().reset_index()
grouped_floor_level.head()
plt.title('樓層等級-數(shù)量')
plt.bar(grouped_floor_level.floor_level, grouped_floor_level.unit_price)
- 由上圖可知,低、中绊袋、高區(qū)的房源數(shù)量基本相等毕匀,都在8000套以上,其中高區(qū)最多愤炸,數(shù)量超過了10000套
計算各樓層等級的平均單價和平均總價平均單價
grouped_floor_level1 = df7.groupby('floor_level').unit_price.mean().reset_index()
grouped_floor_level1
plt.title('樓層等級-平均單價')
plt.bar(grouped_floor_level1.floor_level, grouped_floor_level1.unit_price)
如圖所示期揪,低、中规个、高區(qū)的樓層平均單價在6萬元附近
平均總價
grouped_floor_level2 = df7.groupby('floor_level').total_price.mean().reset_index()
grouped_floor_level2
plt.title('樓層等級-平均總價')
plt.bar(grouped_floor_level2.floor_level, grouped_floor_level2.total_price)
- 如圖所示凤薛,低、中诞仓、高區(qū)樓層平均總價均超過500萬缤苫,其中低區(qū)總價最高,達到590萬
查看缺失值
df2.isnull().sum()
對缺失值進行處理
# 填充floor列中的空值為999
df2.floor = df2.floor.fillna('999')
# 找出floor列中值為999的行號
c_list = df2[df2.floor == '999'].index.tolist()
# 刪除上面查找到的行
df8 = df2.drop(c_list)
df8.isnull().sum()
計算樓層平均單價排名前15的
df2.groupby('floor').unit_price.mean().sort_values(ascending = False).reset_index().head(15)
展示平均單價的波動趨勢:
plt.figure(figsize = (15,5))
df2.groupby('floor').unit_price.mean().plot()
plt.title('樓層數(shù)-單價')
- 由上圖分析可知墅拭,隨著樓層數(shù)的增加活玲,房價也隨之升高;在37層之前谍婉,房價隨樓層數(shù)增加而增加的趨勢比較線性舒憾,但是之后房價隨樓層數(shù)遞增的趨勢波動很大,可能的原因是樓層超過40的住宅數(shù)量較少穗熬,而數(shù)據(jù)量也相對較少镀迂,容易產(chǎn)生誤差。
5.3房價與朝向的關(guān)系
# 查看房屋朝向
df2.orientations.drop_duplicates().values.tolist()
根據(jù)朝向構(gòu)建新的列表
# 根據(jù)朝向重新構(gòu)成一個列表
b_list = list(['朝東','朝東北', '朝東南', '朝東西', '朝北','朝南', '朝南北', '朝西', '朝西北', '朝西南'])
df8 = df2[df2.orientations.isin(b_list)]
grouped_orientations = df8.groupby('orientations').unit_price.mean().sort_values(ascending = False).reset_index()
grouped_orientations
plt.figure(figsize=(12,5))
plt.bar(grouped_orientations.orientations,grouped_orientations.unit_price)
plt.title('朝向-單價')
- 由上圖可知唤蔗,朝向?qū)Ψ績r有一定的影響探遵,朝向南面(南、東南妓柜、西南)的房子總價會高一些箱季,因為南面的房屋采光會比較好,而南北通透的房子單價會比其他朝向的要高一些棍掐。
5.4房價與建筑年代的關(guān)系
df2.isnull().sum()
# 缺失值處理
df2.construction_time = df2.construction_time.fillna('000')
d_list = df2[df2.construction_time == '000'].index.tolist()
df9 = df2.drop(d_list)
由折線圖展示各年份建筑房屋數(shù)量
plt.figure(figsize=(15,5))
df9.groupby('construction_time').unit_price.count().plot()
plt.title('建筑時間-數(shù)量')
- 以上折線圖呈現(xiàn)右側(cè)雙峰形態(tài)藏雏,即分別在1995年和2005年左右出現(xiàn)了兩次房屋修建高峰期,這期間房屋數(shù)量激增塌衰。
計算各個年份平均總價诉稍,作出其折線圖
plt.figure(figsize = (15,5))
df9.groupby('construction_time').total_price.mean().plot()
plt.title('建筑時間-平均總價圖')
計算各個年份平均單價
plt.figure(figsize=(15,5))
df9.groupby('construction_time').unit_price.mean().plot()
plt.title('建筑時間-平均單價圖')
- 由以上分析可知:
- 以上平均總價與建筑時間的趨勢和平均單價與建筑時間的趨勢大致一樣,都呈現(xiàn)左側(cè)單峰形態(tài)最疆。從1920年到1950年間建造的房屋杯巨,其總價和單價均高于之后建造的房屋,分析其原因:從1920年到1950年間建造的房屋努酸,因為建造時間早服爷,其建筑的位置處于現(xiàn)在上海市中心地區(qū),因為其土地、經(jīng)濟仍源、政治等因素心褐,導致現(xiàn)在的高房價。
- 從2015年以來修建的房屋呈現(xiàn)突然上升趨勢笼踩,這也和目前房價不斷升高的趨勢相契合逗爹,這表明房價在短時間內(nèi)不會出現(xiàn)大的下跌現(xiàn)象,是否會出現(xiàn)下一個房價高峰嚎于,還需要考量其他因素進行觀測分析掘而。