數據源:https://tianchi.aliyun.com/competition/entrance/231715/information
導入模塊
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline plt.rc("font",family="SimHei",size="12") #解決中文無法顯示的問題
導入數據
#導入數據 listings=pd.read_csv('F:\\python\\天池_短租數據分析\\listings.csv')
簡單的數據查看
listings.info() listings.head(5) listings.shape listings.describe()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 28452 entries, 0 to 28451 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 28452 non-null int64 1 name 28451 non-null object 2 host_id 28452 non-null int64 3 host_name 28452 non-null object 4 neighbourhood_group 0 non-null float64 5 neighbourhood 28452 non-null object 6 latitude 28452 non-null float64 7 longitude 28452 non-null float64 8 room_type 28452 non-null object 9 price 28452 non-null int64 10 minimum_nights 28452 non-null int64 11 number_of_reviews 28452 non-null int64 12 last_review 17294 non-null object 13 reviews_per_month 17294 non-null float64 14 calculated_host_listings_count 28452 non-null int64 15 availability_365 28452 non-null int64 dtypes: float64(4), int64(7), object(5) memory usage: 3.5+ MB
數據情況如上面截圖,主要是有關可租房屋的信息,字段含義和英文含義基本一致,主要包括:房東ID、房東姓名、所屬行政區、經緯度、房間類型、價格、最小可租天數、評論數量、最后一次評論時間、每月評論占比、可出租房屋、每年可出租時長等
查看數據缺失情況
#數據缺失計算 missing=listings.isnull().sum() missing[missing>0].plot.bar()

缺失比例
#數據缺失比例計算 missing=listings.isnull().sum()/len(listings) missing[missing>0].plot.bar()
可以看出來,一共有四個字段有缺失,其中有一個字段缺失特別嚴重,缺失比例達到了100%,可以刪除,還有2個缺失40%左右,也可以考慮將此刪除
區分數據特征個類別特征
#數據特征 numeric_features = listings.select_dtypes(include=[np.number]) numeric_features.columns #類別特征 categorical_features = listings.select_dtypes(include=[np.object]) categorical_features.columns
類別特征
查看類別特征的值的個數
for cat_fea in categorical_features: print(cat_fea + "的特征分布如下:") print("{}特征有個{}不同的值".format(cat_fea, listings[cat_fea].nunique())) print(listings[cat_fea].value_counts())
類別特征['name', 'host_name', 'neighbourhood', 'room_type', 'last_review']
只保留neighbourhood,'/'前面的值
#使用str.split,記住不要忘記.str,不然會出錯 listings['neighbourhood']=listings['neighbourhood'].str.split('/').str[0]
原來是這樣:
0 朝陽區 / Chaoyang 1 密雲縣 / Miyun 2 東城區 3 東城區 4 朝陽區 / Chaoyang Name: neighbourhood, dtype: object
現在是這樣:
0 朝陽區 1 密雲縣 2 東城區 3 東城區 4 朝陽區 Name: neighbourhood, dtype: object
分析neighbourhood和room_type對和price的關系
#按照neighbourhood和room_type分組,計算每個值的個數和price的均值 neigh_roomtype=listings.groupby(['neighbourhood','room_type']).agg({'id':'size','price':'mean'}) #將ID改為number neigh_roomtype=neigh_roomtype.rename(columns={'id':'number'}) #先對number計算統計可視化等 number_n_r=neigh_roomtype.unstack()['number'] number_n_r.plot(figsize=(12,5),title='圖1:不同房屋類型在不同地區的數量')

畫條形圖
#條形圖 number_n_r.plot.bar(figsize=(12,5),title='圖1:不同房屋類型在不同地區的數量')

畫餅圖
#畫餅圖(sum(1)是按行求和) number_n_r.sum(1).sort_values().plot.pie(figsize=(6,6),autopct='%.2f%%',title='圖2:房屋地區占比')

#畫餅圖(按列求和) number_n_r.sum(0).sort_values().plot.pie(figsize=(6,6),autopct='%.2f%%',title='圖3:房屋類型占比')

不同區域不同房子類型的均價
#先對price計算統計可視化等 price_r=neigh_roomtype.unstack()['price'] price_r.plot.bar(figsize=(12,5),title='圖1:不同房屋類型在不同地區的均價') #先對price計算統計可視化等 price_r=neigh_roomtype.unstack()['price'] price_r.plot(figsize=(12,5),title='圖1:不同房屋類型在不同地區的均價')

計算不同房源均價
#計不同地區均價 listings.groupby('neighbourhood')['price'].mean().sort_values().plot.bar(figsize=(8,8),title='圖4:不同地區房源均價')

不能是這樣,因為這樣沒有考慮個數,直接使用三個值平均,這種做法是錯誤了
price_r.mean(1).sort_values().plot.bar(figsize=(6,6),title='圖2:房屋地區占比')
計算不同房屋類型均價
#不同房屋類型均價 listings.groupby('room_type')['price'].mean().sort_values().plot.bar(figsize=(8,8),title='圖5:不同房屋類型均價')

不同房源地區不同房屋類型均價
#不同房源地區和房子類型均價 n_r_data=listings.groupby(['neighbourhood','room_type'])['price'].mean() plt.figure(figsize=(8,8)) plt.title('圖6:不同房屋類型在不同地區的均價') sns.barplot(x='neighbourhood',y='price',hue='room_type',data=n_r_data.reset_index()) #或者是這樣子 #先對price計算統計可視化等 price_r=neigh_roomtype.unstack()['price'] price_r.plot.bar(figsize=(12,5),title='圖1:不同房屋類型在不同地區的均價')


查看name 和host_name
listings[['name', 'host_name']].head()

房東名字應該是沒有什么信息的,可以考慮去掉,name可以從中提取一些特征
查看最后last_review
listings['last_review'].head()
0 2019-03-04 1 2017-10-08 2 2019-02-05 3 2016-12-03 4 2018-08-01 Name: last_review, dtype: object
可以構造一些有用的特征
數值特征
查看數值特征的值的分布,連續還是離散的
''' Index(['id', 'host_id', 'neighbourhood_group', 'latitude', 'longitude', 'price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month', 'calculated_host_listings_count', 'availability_365'], dtype='object') ''' for i in numeric_features.columns: print(i,listings[i].value_counts())
1.id和host_id是沒有什么信息的可以刪除
#可以先保留一下id ,然后再刪除 id=listings['id'] listings=listings.drop(['id', 'host_id'],axis=1)
2.由於neighbourhood_group的值全部一樣,都是空值,因此將此刪除
listings=listings.drop('neighbourhood_group',axis=1)
3.經緯度,可能和房源區域強相關
sns.regplot('latitude','price',data=listings) sns.regplot('longitude','price',data=listings)


4.最小可租天數
sns.regplot('minimum_nights','price',data=listings)

sns.boxplot('minimum_nights',data=listings)

這肯定有異常值了,而且一般不都是最小入住天數是1天嗎
#看的出來最小入住天數是1晚,還有30天這個值還挺多的有609個,應該是月租 listings['minimum_nights'].value_counts().sort_index()
5.評論數量、最后一次評論時間(單獨拿出來)、每月評論占比、可出租房屋、每年可出租時長
for i in ['number_of_reviews', 'calculated_host_listings_count', 'availability_365']: sns.regplot(i,'price',data=listings) plt.show()



目標變量price
sns.boxplot(listings['price']) sns.distplot(listings['price'])


大於10000的值影響太大了,可以只畫10000以下的
sns.distplot(listings[listings['price']<=10000]['price'])

查看一下描述性
listings['price'].describe()
count 28452.000000 mean 611.203325 std 1623.535077 min 0.000000 25% 235.000000 50% 389.000000 75% 577.000000 max 68983.000000 Name: price, dtype: float64
再看一下1000以下的
sns.distplot(listings[listings['price']<=1000]['price'])

為什么會有0,好詭異,青年旅館嗎
listings['price'].value_counts().sort_index() #0 3
log一下
sns.distplot(np.log(listings['price']+1)) sns.distplot(np.log(listings[listings['price']<=1000]['price']+1))


特征工程
先復制一份數據,省得對原數據造成影響
train=listings.copy()
先對類別特征進行構造特征


