1.“未來杯 城市-房產租金預測”之任務分析



一、賽題說明

1.1題目說明

賽題鏈接:“未來杯” 城市-房產租金預測

比賽要求參賽選手根據給定的數據集,建立模型,預測房屋租金。

數據集中的數據類別包括租賃房源、小區、二手房、配套、新房、土地、人口、客戶、真實租金等。

這是典型的迴歸預測

1.2 預測指標

迴歸結果評價標準採用R-Square

R2(R-Square)的公式爲

殘差平方和:
在這裏插入圖片描述

總平均值:
在這裏插入圖片描述

其中 yˉ\bar{y} 表示 𝑦 的平均值, 得到 R2R^{2} 表達式爲:
在這裏插入圖片描述

R2R^{2} 用於度量因變量的變異中可由自變量解釋部分所佔的比例,取值範圍是 0~1,R2R^{2}越接近1,表明迴歸平方和佔總平方和的比例越大,迴歸線與各觀測點越接近,用x的變化來解釋y值變化的部分就越多,迴歸的擬合程度就越好。所以 R2R^{2} 也稱爲擬合優度(Goodness of Fit)的統計量。

y_{i}表示真實值,y^i\hat{y}_{i}表示預測值,yiˉ\bar{y_{i}}表示樣本均值。得分越高擬合效果越好。

1.3 數據概況

1.租賃基本信息

  • ID——房屋編號
  • area——房屋面積
  • rentType——出租方式:整租/合租/未知
  • houseType——房型
  • houseFloor——房間所在樓層:高/中/低
  • totalFloor——房間所在的總樓層數
  • houseToward——房間朝向
  • houseDecoration——房屋裝修
  • tradeTime——成交日期
  • tradeMoney——成交租金

2.小區信息

  • CommunityName——小區名稱
  • city——城市
  • region——地區
  • plate——區域板塊
  • buildYear——小區建築年代
  • saleSecHouseNum——該板塊當月二手房掛牌房源數

3.配套設施

  • subwayStationNum——該板塊地鐵站數量
  • busStationNum——該板塊公交站數量
  • interSchoolNum——該板塊國際學校的數量
  • schoolNum——該板塊公立學校的數量
  • privateSchoolNum——該板塊私立學校數量
  • hospitalNum——該板塊綜合醫院數量
  • DrugStoreNum——該板塊藥房數量
  • gymNum——該板塊健身中心數量
  • bankNum——該板塊銀行數量
  • shopNum——該板塊商店數量
  • parkNum——該板塊公園數量
  • mallNum——該板塊購物中心數量
  • superMarketNum——該板塊超市數量

4.其他信息

  • totalTradeMoney——該板塊當月二手房成交總金額
  • totalTradeArea——該板塊二手房成交總面積
  • tradeMeanPrice——該板塊二手房成交均價
  • tradeSecNum——該板塊當月二手房成交套數
  • totalNewTradeMoney——該板塊當月新房成交總金額
  • totalNewTradeArea——該板塊當月新房成交的總面積
  • totalNewMeanPrice——該板塊當月新房成交均價
  • tradeNewNum——該板塊當月新房成交套數
  • remainNewNum——該板塊當月新房未成交套數
  • supplyNewNum——該板塊當月新房供應套數
  • supplyLandNum——該板塊當月土地供應幅數
  • supplyLandArea——該板塊當月土地供應面積
  • tradeLandNum——該板塊當月土地成交幅數
  • tradeLandArea——該板塊當月土地成交面積
  • landTotalPrice——該板塊當月土地成交總價
  • landMeanPrice——該板塊當月樓板價(元/m^{2})
  • totalWorkers——當前板塊現有的辦公人數
  • newWorkers——該板塊當月流入人口數(現招聘的人員)
  • residentPopulation——該板塊常住人口
  • pv——該板塊當月租客瀏覽網頁次數
  • uv——該板塊當月租客瀏覽網頁總人數
  • lookNum——線下看房次數

二、數據分析

2.1 總體瀏覽數據


#coding:utf-8
#導入warnings包,利用過濾器來實現忽略警告語句。
import warnings
warnings.filterwarnings('ignore')

# GBDT
from sklearn.ensemble import GradientBoostingRegressor
# XGBoost
import xgboost as xgb
# LightGBM
import lightgbm as lgb

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

#載入數據
data_train = pd.read_csv('F:\\實驗\\比賽\\房價預測\\數據集\\train_data.csv')
data_train['Type'] = 'Train'
data_test = pd.read_csv('F:\\實驗\\比賽\\房價預測\\數據集\\test_a.csv')
data_test['Type'] = 'Test'
data_all = pd.concat([data_train, data_test], ignore_index=True)

# 總體情況
print(data_train.info())
print(data_train.describe())
data_train.head()

結果(截取部分):
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

簡要分析

  • 該份訓練集包含 41440行×52列數據;
  • 目標變量是 真實房租價格- tradeMoney;
  • 大多數數據都是int或float型;有部分字段是object型,即文本型中文或英文的,如rentType字段,這些字段在之後需要做處理。

2.2 分類特徵和連續型特徵

# 根據特徵含義和特徵一覽,大致可以判斷出數值型和類別型特徵如下
categorical_feas = ['rentType', 'houseType', 'houseFloor', 'region', 'plate', 'houseToward', 'houseDecoration',
    'communityName','city','buildYear']

numerical_feas=['ID','area','totalFloor','saleSecHouseNum','subwayStationNum',
    'busStationNum','interSchoolNum','schoolNum','privateSchoolNum','hospitalNum',
    'drugStoreNum','gymNum','bankNum','shopNum','parkNum','mallNum','superMarketNum',
    'totalTradeMoney','totalTradeArea','tradeMeanPrice','tradeSecNum','totalNewTradeMoney',
    'totalNewTradeArea','tradeNewMeanPrice','tradeNewNum','remainNewNum','supplyNewNum',
    'supplyLandNum','supplyLandArea','tradeLandNum','tradeLandArea','landTotalPrice',
    'landMeanPrice','totalWorkers','newWorkers','residentPopulation','pv','uv','lookNum']

2.3 缺失值分析

def missing_values(df):
    alldata_na = pd.DataFrame(df.isnull().sum(), columns={'missingNum'})
    alldata_na['existNum'] = len(df) - alldata_na['missingNum']
    alldata_na['sum'] = len(df)
    alldata_na['missingRatio'] = alldata_na['missingNum']/len(df)*100
    alldata_na['dtype'] = df.dtypes
    #ascending:默認True升序排列;False降序排列
    alldata_na = alldata_na[alldata_na['missingNum']>0].reset_index().sort_values(by=['missingNum','index'],ascending=[False,True])
    alldata_na.set_index('index',inplace=True)
    return alldata_na

missing_values(data_train)

在這裏插入圖片描述

簡要分析

  • 這裏採用編寫函數的方式來直接獲取結果(這種方式會在之後反覆用到,建議大家儘早養成函數式編寫的習慣);
  • 其實在總體情況一覽中,info()函數也能看出來。
  • 結果是,僅有pv、uv存在缺失值,後面再探究會發現缺失的都是屬於同一個plate,可能是官方直接刪除了該plate的pv、uv。

2.4 單調特徵列分析

#是否有單調特徵列(單調的特徵列很大可能是時間)
def incresing(vals):
    cnt = 0
    len_ = len(vals)
    for i in range(len_-1):
        if vals[i+1] > vals[i]:
            cnt += 1
    return cnt

fea_cols = [col for col in data_train.columns]
for col in fea_cols:
    cnt = incresing(data_train[col].values)
    if cnt / data_train.shape[0] >= 0.55:
        print('單調特徵:',col)
        print('單調特徵值個數:', cnt)
        print('單調特徵值比例:', cnt / data_train.shape[0])

單調特徵: tradeTime
單調特徵值個數: 24085
單調特徵值比例: 0.5812017374517374

簡要分析

  • 先編寫判斷單調的函數 incresing, 然後再應用到每列上;
  • 單調特徵是 tradeTime,爲時間列。
  • 多說句額外的,時間列在特徵工程的時候,不同的情況下能有很多的變種形式,比如按年月日分箱,或者按不同的維度在時間上聚合分組,等等。

2.5 特徵nunique分佈


# 特徵nunique分佈
for feature in categorical_feas:
    print(feature + "的特徵分佈如下:")
    print(data_train[feature].value_counts())
    if feature != 'communityName': # communityName值太多,暫且不看圖表
        plt.hist(data_all[feature], bins=3)
        plt.show()

結果(部分截圖):
在這裏插入圖片描述

print(data_train['communityName'].value_counts())
print(data_test['communityName'].value_counts())

結果:
XQ01834    358
XQ01274    192
XQ02273    188
XQ03110    185
XQ02337    173
          ... 
XQ01302      1
XQ02870      1
XQ01972      1
XQ02671      1
XQ01787      1
Name: communityName, Length: 4236, dtype: int64
XQ03306    1
XQ00629    1
XQ01830    1
XQ00534    1
XQ02021    1
          ..
XQ03596    1
XQ03784    1
XQ00332    1
XQ01140    1
XQ00239    1
Name: communityName, Length: 2469, dtype: int64

簡要分析

  • 用自帶函數value_counts() 來得到每個分類變量的種類分佈; 並且簡單畫出柱狀圖。
  • rentType:4種,且絕大多數是無用的未知方式;
  • houseType:104種,絕大多數在3室及以下;
  • houseFloor:3種,分佈較爲均勻;
  • region: 15種;
  • plate: 66種;
  • houseToward: 10種;
  • houseDecoration: 4種,一大半是其他;
  • buildYear: 80種;
  • communityName:4236種,且分佈較爲稀疏;
  • 此步驟是爲之後數據處理和特徵工程做準備,先理解每個字段的含義以及分佈,之後需要根據實際含義對分類變量做不同的處理。

2.6 統計特徵值頻次大於100的特徵

# 統計特徵值出現頻次大於100的特徵
for feature in categorical_feas:
    df_value_counts = pd.DataFrame(data_train[feature].value_counts())
    df_value_counts = df_value_counts.reset_index()
    df_value_counts.columns = [feature, 'counts'] # change column names
    print(df_value_counts[df_value_counts['counts'] >= 100])

結果(部分截圖):
在這裏插入圖片描述

簡要分析

  • 此步驟和特徵nunique分佈結合步驟結合起來看,有一些小於100的是可以直接統一歸類爲其他的

2.7 Label分佈

# Labe 分佈
fig,axes = plt.subplots(2,3,figsize=(20,5))
fig.set_size_inches(20,12)
sns.distplot(data_train['tradeMoney'],ax=axes[0][0])
sns.distplot(data_train[(data_train['tradeMoney']<=20000)]['tradeMoney'],ax=axes[0][1])
sns.distplot(data_train[(data_train['tradeMoney']>20000)&(data_train['tradeMoney']<=50000)]['tradeMoney'],ax=axes[0][2])
sns.distplot(data_train[(data_train['tradeMoney']>50000)&(data_train['tradeMoney']<=100000)]['tradeMoney'],ax=axes[1][0])
sns.distplot(data_train[(data_train['tradeMoney']>100000)]['tradeMoney'],ax=axes[1][1])

結果截圖
在這裏插入圖片描述

print("money<=10000",len(data_train[(data_train['tradeMoney']<=10000)]['tradeMoney']))
print("10000<money<=20000",len(data_train[(data_train['tradeMoney']>10000)&(data_train['tradeMoney']<=20000)]['tradeMoney']))
print("20000<money<=50000",len(data_train[(data_train['tradeMoney']>20000)&(data_train['tradeMoney']<=50000)]['tradeMoney']))
print("50000<money<=100000",len(data_train[(data_train['tradeMoney']>50000)&(data_train['tradeMoney']<=100000)]['tradeMoney']))
print("100000<money",len(data_train[(data_train['tradeMoney']>100000)]['tradeMoney']))

結果
money<=10000 38964
10000<money<=20000 1985
20000<money<=50000 433
50000<money<=100000 39
100000<money 19

簡要分析

  • 將目標變量tradeMoney分組,並查看每組間的分佈; 可以看出絕大多數都是集中在10000元以內的,並且從圖中可以看到該分佈是右偏的。
  • 這裏只是一種實現方式,完全可以將tradeMoney和其他字段一起結合起來查看,比如樓層高低,地區板塊。
發佈了90 篇原創文章 · 獲贊 37 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章