ToB企服应用市场:ToB评测及商务社交产业平台

标题: 数据分析(以kaggle上的加州房价为例) [打印本页]

作者: 商道如狼道    时间: 2023-9-12 23:09
标题: 数据分析(以kaggle上的加州房价为例)
数据来源:House Prices - Advanced Regression Techniques

参考文献:
1. 导入数据
  1. import pandas as pd
  2. import warnings
  3. warnings.filterwarnings('ignore') # 忽略警告
复制代码
  1. df_train = pd.read_csv('./house-prices-advanced-regression-techniques/train.csv')
复制代码
  1. df_train.columns
复制代码
  1. Index(['Id', 'MSSubClass', 'MSZoning', 'LotFrontage', 'LotArea', 'Street',
  2.        'Alley', 'LotShape', 'LandContour', 'Utilities', 'LotConfig',
  3.        'LandSlope', 'Neighborhood', 'Condition1', 'Condition2', 'BldgType',
  4.        'HouseStyle', 'OverallQual', 'OverallCond', 'YearBuilt', 'YearRemodAdd',
  5.        'RoofStyle', 'RoofMatl', 'Exterior1st', 'Exterior2nd', 'MasVnrType',
  6.        'MasVnrArea', 'ExterQual', 'ExterCond', 'Foundation', 'BsmtQual',
  7.        'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinSF1',
  8.        'BsmtFinType2', 'BsmtFinSF2', 'BsmtUnfSF', 'TotalBsmtSF', 'Heating',
  9.        'HeatingQC', 'CentralAir', 'Electrical', '1stFlrSF', '2ndFlrSF',
  10.        'LowQualFinSF', 'GrLivArea', 'BsmtFullBath', 'BsmtHalfBath', 'FullBath',
  11.        'HalfBath', 'BedroomAbvGr', 'KitchenAbvGr', 'KitchenQual',
  12.        'TotRmsAbvGrd', 'Functional', 'Fireplaces', 'FireplaceQu', 'GarageType',
  13.        'GarageYrBlt', 'GarageFinish', 'GarageCars', 'GarageArea', 'GarageQual',
  14.        'GarageCond', 'PavedDrive', 'WoodDeckSF', 'OpenPorchSF',
  15.        'EnclosedPorch', '3SsnPorch', 'ScreenPorch', 'PoolArea', 'PoolQC',
  16.        'Fence', 'MiscFeature', 'MiscVal', 'MoSold', 'YrSold', 'SaleType',
  17.        'SaleCondition', 'SalePrice'],
  18.       dtype='object')
复制代码
  1. df_train['SalePrice'].describe()
复制代码
  1. count      1460.000000
  2. mean     180921.195890
  3. std       79442.502883
  4. min       34900.000000
  5. 25%      129975.000000
  6. 50%      163000.000000
  7. 75%      214000.000000
  8. max      755000.000000
  9. Name: SalePrice, dtype: float64
复制代码
2. 变量分析
  1. import seaborn as sns
复制代码
  1. # 绘制售价的直方图
  2. sns.distplot(df_train['SalePrice']);
复制代码
  1. # 输出偏度和峰度
  2. print("Skewness: %f" % df_train['SalePrice'].skew())
  3. print("Kurtosis: %f" % df_train['SalePrice'].kurt())
复制代码
  1. Skewness: 1.882876
  2. Kurtosis: 6.536282
复制代码
  1. # 绘制GrLivArea(生活面积)的散点图
  2. var = 'GrLivArea'
  3. data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
  4. data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000));
复制代码
  1. # 绘制TotalBsmtSF(地下室面积)的散点图
  2. var = 'TotalBsmtSF'
  3. data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
  4. data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000));
复制代码
  1. import matplotlib.pyplot as plt
复制代码
  1. # 绘制OverallQual(房屋整体材料和装修质量)的箱线图
  2. var = 'OverallQual'
  3. data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
  4. f, ax = plt.subplots(figsize=(8, 6))
  5. fig = sns.boxplot(x=var, y='SalePrice', data=data)
  6. fig.axis(ymin=0, ymax=800000);
复制代码
  1. # 绘制YearBuilt(建造年份)的箱线图
  2. var = 'YearBuilt'
  3. data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
  4. f, ax = plt.subplots(figsize=(16, 8))
  5. fig = sns.boxplot(x=var, y='SalePrice', data=data)
  6. fig.axis(ymin=0, ymax=800000)
  7. plt.xticks(rotation=90);    # 旋转x轴标签90度
复制代码

3. 更近进一步的变量分析

第二步只是凭着直觉对数据进行了初步的分析,下面我们将对数据进行更进一步的分析。
  1. # 绘制变量相关矩阵
  2. corrmat = df_train.corr(numeric_only=True) # 仅对数值型变量进行相关分析
  3. f, ax = plt.subplots(figsize=(12, 9))
  4. sns.heatmap(corrmat, vmax=.8, square=True);
复制代码
  1. import numpy as np
复制代码
  1. # SalePrice与其他变量的相关系数
  2. k = 10
  3. cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index # 与SalePrice相关系数最大的10个变量的索引
  4. cm = np.corrcoef(df_train[cols].values.T) # 计算相关系数矩阵
  5. sns.set(font_scale=1.25)
  6. hm = sns.heatmap(cm, annot=True, fmt='.2f', annot_kws={'size': 10},
  7.                  yticklabels=cols.values, xticklabels=cols.values)  # 设置annot=True,显示相关系数
  8. plt.show()
复制代码

对于GarageCars和GarageArea,两者有很强的关联性,因此选择保留GrageCars,因为它与SalePrice的相关性更高;TotalBsmtSF和1stFloor(First Floor square feet)也有很强的关联性,地下室面积一般情况下不会大于一楼的面积,故选择保留TotalBsmtSF。
因此最终保留了7个与SalePrice关联最大的7个变量,分别是OverallQual、GrLivArea、GarageCars、TotalBsmtSF、FullBath、YearBuilt和YearRemodAdd。
  1. # 绘制变量之间的pairplot散点图
  2. sns.set()
  3. cols = ['SalePrice', 'OverallQual', 'GrLivArea', 'GarageCars', 'TotalBsmtSF',
  4.         'FullBath', 'YearBuilt', 'YearRemodAdd']
  5. sns.pairplot(df_train[cols], size=2.5)
  6. plt.show()
复制代码

观察成对散点图:
TotalBsmtSF和GrLivArea两者的图像上有一条直线,仿佛边界一般。说明地下室面积和生活面积成正比。就像上面提到的地下室面积和一楼面积的关系一样。
SalePrice和YearBuilt的散点仿佛指数函数一般,说明房价随着建造年份的增加而增加。
4. 缺失值处理
  1. total = df_train.isnull().sum().sort_values(ascending=False) # 统计每个变量的缺失值个数
  2. percent = (df_train.isnull().sum() / len(df_train)).sort_values(ascending=False) # 统计每个变量的缺失值比例
  3. missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
  4. missing_data.head(20)
复制代码
            Total      Percent                  PoolQC      1453      0.995205              MiscFeature      1406      0.963014              Alley      1369      0.937671              Fence      1179      0.807534              MasVnrType      872      0.597260              FireplaceQu      690      0.472603              LotFrontage      259      0.177397              GarageYrBlt      81      0.055479              GarageCond      81      0.055479              GarageType      81      0.055479              GarageFinish      81      0.055479              GarageQual      81      0.055479              BsmtFinType2      38      0.026027              BsmtExposure      38      0.026027              BsmtQual      37      0.025342              BsmtCond      37      0.025342              BsmtFinType1      37      0.025342              MasVnrArea      8      0.005479              Electrical      1      0.000685              Id      0      0.000000   
  1. df_train = df_train.drop((missing_data[missing_data['Total'] > 1]).index, axis=1) # 将缺失数量大于1的列删去
  2. df_train = df_train.drop(df_train.loc[df_train['Electrical'].isnull()].index) # 将Electrical缺失的行删去
  3. df_train.isnull().sum().max() # 检查是否还有缺失值
复制代码
  1. 0
复制代码
  1. from sklearn.preprocessing import StandardScaler
复制代码
  1. saleprice_scaled = StandardScaler().fit_transform(df_train['SalePrice'].to_numpy()[:, np.newaxis])
复制代码
  1. # 输出异常值
  2. low_range = saleprice_scaled[saleprice_scaled[:, 0].argsort()][:10]
  3. high_range = saleprice_scaled[saleprice_scaled[:, 0].argsort()][-10:]
  4. print('outer range (low) of the distribution:')
  5. print(low_range)
  6. print('\nouter range (high) of the distribution:')
  7. print(high_range)
复制代码
  1. outer range (low) of the distribution:
  2. [[-1.83820775]
  3. [-1.83303414]
  4. [-1.80044422]
  5. [-1.78282123]
  6. [-1.77400974]
  7. [-1.62295562]
  8. [-1.6166617 ]
  9. [-1.58519209]
  10. [-1.58519209]
  11. [-1.57269236]]
  12. outer range (high) of the distribution:
  13. [[3.82758058]
  14. [4.0395221 ]
  15. [4.49473628]
  16. [4.70872962]
  17. [4.728631  ]
  18. [5.06034585]
  19. [5.42191907]
  20. [5.58987866]
  21. [7.10041987]
  22. [7.22629831]]
复制代码
  1. # 重新绘制GrLivArea和SalePrice的散点图
  2. var = 'GrLivArea'
  3. data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
  4. data.plot.scatter(x=var, y='SalePrice', ylim=(0, 800000));
复制代码

上图中右下角的两个点是异常值,因为它们的GrLivArea很大,但是售价很低。因此将它们删除。
  1. lines = df_train.sort_values(by='GrLivArea', ascending=False)[:2]
  2. df_train = df_train.drop(lines.index)
复制代码
5. 测试数据

对于结果的计算分析,需要建立在一定的数据假设上。通常,需要考虑这四种情况:
  1. from scipy.stats import norm
  2. from scipy import stats
复制代码
  1. # 绘制直方图与正态概率图
  2. sns.distplot(df_train['SalePrice'], fit=norm)
  3. fig = plt.figure()
  4. res = stats.probplot(df_train['SalePrice'], plot=plt)
复制代码

  1. # 对SalePrice进行log转换使其更接近正态分布,并重新绘制直方图与正态概率图
  2. df_train['SalePrice'] = np.log(df_train['SalePrice'])
  3. sns.distplot(df_train['SalePrice'], fit=norm)
  4. fig = plt.figure()
  5. res = stats.probplot(df_train['SalePrice'], plot=plt)
复制代码

  1. # 同理,对GrLivArea绘制直方图与正态概率图
  2. sns.distplot(df_train['GrLivArea'], fit=norm)
  3. fig = plt.figure()
  4. res = stats.probplot(df_train['GrLivArea'], plot=plt)
复制代码

  1. # 对GrLivArea进行log转换使其更接近正态分布,并重新绘制直方图与正态概率图
  2. df_train['GrLivArea'] = np.log(df_train['GrLivArea'])
  3. sns.distplot(df_train['GrLivArea'], fit=norm)
  4. fig = plt.figure()
  5. res= stats.probplot(df_train['GrLivArea'], plot=plt)
复制代码

  1. # 还有TotalBsmtSF
  2. sns.distplot(df_train['TotalBsmtSF'], fit=norm)
  3. fig = plt.figure()
  4. res = stats.probplot(df_train['TotalBsmtSF'], plot=plt)
复制代码


由于一些房子没有地下室,导致有很多0值,因此不能对TotalBsmtSF进行log转换。
这里创建一个新的变量,如果TotalBsmtSF>0,则为1,否则为0。
  1. df_train['HasBsmt'] = pd.Series(len(df_train['TotalBsmtSF']), index=df_train.index)
  2. df_train['HasBsmt'] = 0
  3. df_train.loc[df_train['TotalBsmtSF'] > 0, 'HasBsmt'] = 1
复制代码
  1. # 对HasBsmt为1的数据进行log转换
  2. df_train.loc[df_train['HasBsmt'] == 1, 'TotalBsmtSF'] = np.log(df_train['TotalBsmtSF'])
  3. sns.distplot(df_train[df_train['TotalBsmtSF'] > 0]['TotalBsmtSF'], fit=norm)
  4. fig = plt.figure()
  5. res = stats.probplot(df_train[df_train['TotalBsmtSF'] > 0]['TotalBsmtSF'], plot=plt)
复制代码


对于同方差的检验,可以绘制散点图。如果散点呈现锥形(就像之前画的),这意味着数据的方差随着自变量的增加而增加,通常被称为异方差;变量是同方差,散点的数据应该分布在一条直线附近。
现在我们来看一下经过log运算后的SalePrice和GrLivArea还有TotalBsmtSF的散点图。
  1. plt.scatter(df_train['GrLivArea'], df_train['SalePrice']);
复制代码
  1. plt.scatter(df_train[df_train['TotalBsmtSF'] > 0]['TotalBsmtSF'], df_train[df_train['TotalBsmtSF'] > 0]['SalePrice']);
复制代码

6. 哑变量
  1. # 将类别变量转换为哑变量
  2. df_train = pd.get_dummies(df_train)
复制代码
总结

本次使用了pandas库和seaborn库对数据进行了初步的分析,对数据的缺失值进行了处理,对数据进行了转换,最后将类别变量转换为哑变量。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4