前言

现在已经学到了数据规整与合并这一章,为了加深对数据分析的理解接下来需要做个小项目练习一下。

目的

  • 通过项目能够真实的了解到数据分析是做什么的
  • 加深对pandas的熟悉程度
  • 重新梳理一下目前学到的那些基础知识,查缺补漏

前期准备
此次项目准备对2018年北京链家网的二手房数据做一次分析
数据来源:Python数据科学的公众号
工具:暂时还是使用iTerm2,还未找到更合适的开发工具。Sublime Text2目前也在用,这次项目小不打算用这个。

导入数据文件并进行初步观察
这些观察包括了解数据特征的缺失值,异常值,以及大概的描述性统计。

In [10]: lianjia_df = pd.read_csv('lianjia/lianjia.csv')

# 先查看前5行数据
In [11]: lianjia_df.head(n=5)

In [12]: display(lianjia_df.head(5))
  Direction District Elevator  Floor    Garden            Id Layout   Price Region Renovation   Size  Year
0        东西      灯市口      NaN      6  锡拉胡同21号院  101102647043   3室1厅   780.0     东城         精装   75.0  1988
1        南北       东单      无电梯      6     东华门大街  101102650978   2室1厅   705.0     东城         精装   60.0  1988
2        南西      崇文门      有电梯     16     新世界中心  101102672743   3室1厅  1400.0     东城         其他  210.0  1996
3         南      崇文门      NaN      7    兴隆都市馨园  101102577410   1室1厅   420.0     东城         精装   39.0  2004
4         南      陶然亭      有电梯     19    中海紫御公馆  101102574696   2室2厅   998.0     东城         精装   90.0  2010
In [14]: lianjia_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 23677 entries, 0 to 23676
Data columns (total 12 columns):
Direction     23677 non-null object
District      23677 non-null object
Elevator      15440 non-null object
Floor         23677 non-null int64
Garden        23677 non-null object
Id            23677 non-null int64
Layout        23677 non-null object
Price         23677 non-null float64
Region        23677 non-null object
Renovation    23677 non-null object
Size          23677 non-null float64
Year          23677 non-null int64
dtypes: float64(2), int64(3), object(7)
memory usage: 2.2+ MB

可以很直接的看到Elevator的值存在着大量的缺失,那先对缺失数据做处理。这里其实可以做填充,因为正常情况下楼层高于6层的都会有电梯,相反则没有。

In [71]: lianjia_df['Elevator'].value_counts()
Out[71]:
有电梯    9342
无电梯    6078
精装       11
毛坯        7
简装        2

看到在Elevator中存在精装、毛培等异常值,先删除

In [75]: lianjia_df['Elevator'] = lianjia_df.loc[(lianjia_df['Elevator'] == '有电梯') | (lianjia_df['Elevator']=='无电梯'), 'Elevator']

In [76]: lianjia_df['Elevator'].value_counts()
Out[76]:
有电梯    9342
无电梯    6078   # 总共23000多条数据,这里明显不够,说明有大量空缺值
Name: Elevator, dtype: int64

再填充电梯情况:

# 这里要直接修改数据了,所以先copy一下
In [90]: df = lianjia_df.copy()

In [91]: df.loc[(df['Floor'] > 6) & (df['Elevator'].isnull()), 'Elevator'] = '有电梯'

In [92]: df.loc[(df['Floor'] <=6) & (df['Elevator'].isnull()), 'Elevator'] = '无电梯'

In [96]: df['Elevator'].value_counts()
Out[96]:
有电梯    14025
无电梯     9652
# 现在

现在空缺值处理完成了,接下来检查下有没有异常值情况:

In [14]: lianjia_df_dorped.describe()
Out[14]:
              Floor            Id         Price          Size          Year
count  15440.000000  1.544000e+04  15440.000000  15440.000000  15440.000000
mean      13.037435  1.011023e+11    622.969326     99.059909   2001.132124
std        7.651691  5.934382e+05    411.791294     47.552860      8.804468
min        1.000000  1.010886e+11     68.500000      2.000000   1950.000000
25%        6.000000  1.011022e+11    378.000000     66.000000   1997.000000
50%       11.000000  1.011024e+11    510.000000     89.000000   2003.000000
75%       18.000000  1.011026e+11    730.000000    119.250000   2007.000000
max       57.000000  1.011028e+11   6000.000000   1019.000000   2016.000000

虽然不大清楚北京有没有价值6000万的房子,但是2平方以及1019平方的房子这个肯定是不现实的。看一下数据情况:

In [17]: df.loc[df['Size'] < 20]
Out[17]:
      Direction District Elevator  Floor   Garden            Id Layout   Price Region Renovation  Size  Year
134           西       沙河      有电梯     17   北街家园七区  101102651491   1室1厅   180.0     昌平         简装  19.0  2010
1168   240.97平米       长阳       毛坯      5     世茂维拉  101102253577   叠拼别墅  1080.0     房山         南北   5.0  2015
1458   242.78平米       长阳       毛坯      5     世茂维拉  101102217569   叠拼别墅  1100.0     房山         南北   5.0  2015
1797   242.96平米       长阳       精装      5     世茂维拉  101101911559   叠拼别墅   980.0     房山         南北   5.0  2015
2268   295.88平米     顺义其它       精装      4    龙湖好望山  101102431983   叠拼别墅  1000.0     顺义         南北   4.0  2014
2274   295.01平米     顺义其它       精装      4     鹭峯国际  101102300614   叠拼别墅  1450.0     顺义         南北   5.0  2014
2276   292.31平米     顺义其它       毛坯      3    龙湖好望山  101102013095   叠拼别墅   860.0     顺义         南北   4.0  2014
2432   294.42平米     顺义其它       精装      5    龙湖好望山  101101141445   叠拼别墅   980.0     顺义         南北   6.0  2013
4078    427.5平米      西红门       精装      3    鸿坤林语墅  101102023530   叠拼别墅  3150.0     大兴         南北   4.0  2015
4079    361.8平米      西红门       精装      4    鸿坤林语墅  101102460862   叠拼别墅  2380.0     大兴         南北   4.0  2015
4761   386.83平米      西红门       精装      3    鸿坤林语墅  101102411099   叠拼别墅  2700.0     大兴         南北   5.0  2015
7533   107.93平米      回龙观       简装      4   龙城花园N区  101101993058   叠拼别墅   620.0     昌平         南北   2.0  1997
8765   195.32平米     通州其它       毛坯      6     旭辉御锦  101102638903   叠拼别墅   780.0     通州         南北   5.0  2014
9020   259.87平米     通州其它       精装      6     旭辉御锦  101101801342   叠拼别墅  1120.0     通州         南北   4.0  2014
9080   259.76平米     通州其它       毛坯      6     旭辉御锦  101102046256   叠拼别墅  1050.0     通州         南北   4.0  2014
9203   260.07平米     通州其它       精装      6     旭辉御锦  101102490792   叠拼别墅  1050.0     通州         南北   4.0  2014
9254    264.6平米     通州其它       毛坯      6     旭辉御锦  101102440907   叠拼别墅  1100.0     通州         南北   4.0  2014
11531  335.51平米       丽泽       毛坯      6     西宸原著  101102306757   叠拼别墅  4000.0     丰台         南北   4.0  2016
14298  266.61平米       西山       精装      3   中间建筑一区  101101869900   叠拼别墅  1350.0     海淀         南北   8.0  2007
15334  203.73平米       西山       简装      4  西山美墅馆F区  101102520575   叠拼别墅  2200.0     海淀         南北   4.0  2004
17311   523.4平米      大望路       精装      5     首府官邸  101102432328   叠拼别墅  4500.0     朝阳         南北   5.0  2007
22350         南       东四      有电梯      3    华人一品阁  101101915230  1房间1卫    90.0     东城         简装  16.0  2006
22393         南       东四      有电梯      3    华人一品阁  101101915213  1房间1卫    90.0     东城         简装  16.0  2006

我觉得16平的房子应该会有,但是小于10平方的房子肯定是异常数据,删掉!

In [30]: df = df[df['Size'] > 10]

In [32]: df.describe()
Out[32]:
              Floor            Id         Price          Size          Year
count  15420.000000  1.542000e+04  15420.000000  15420.000000  15420.000000
mean      13.048314  1.011023e+11    621.608067     99.182490   2001.117639
std        7.650579  5.936816e+05    408.445645     47.461617      8.799356
min        1.000000  1.010886e+11     68.500000     16.000000   1950.000000
25%        6.000000  1.011022e+11    377.750000     66.000000   1997.000000
50%       11.000000  1.011024e+11    510.000000     89.000000   2003.000000
75%       18.000000  1.011026e+11    730.000000    120.000000   2007.000000
max       57.000000  1.011028e+11   6000.000000   1019.000000   2016.000000

同样平方大的离谱的异常值也要删除

In [34]: df.loc[df['Size'] > 1000]
Out[34]:
     Direction District Elevator  Floor   Garden            Id Layout   Price Region Renovation    Size  Year
8754         南     通州其它      有电梯      8  新华联科技大厦  101102019411  1房间0卫  1700.0     通州         简装  1019.0  2009

发现这个大于1000平的是个办公楼,属于异常删掉

In [35]: df = df.loc[df['Size'] < 1000]

Size数据异常的也清理掉了

In [36]: df.describe()
Out[36]:
              Floor            Id         Price          Size          Year
count  15420.000000  1.542000e+04  15420.000000  15420.000000  15420.000000
mean      13.048314  1.011023e+11    621.608067     99.182490   2001.117639
std        7.650579  5.936816e+05    408.445645     47.461617      8.799356
min        1.000000  1.010886e+11     68.500000     16.000000   1950.000000
25%        6.000000  1.011022e+11    377.750000     66.000000   1997.000000
50%       11.000000  1.011024e+11    510.000000     89.000000   2003.000000
75%       18.000000  1.011026e+11    730.000000    120.000000   2007.000000
max       57.000000  1.011028e+11   6000.000000   1019.000000   2016.000000

再看看其他数据有异常或者空缺情况

In [101]: df['Renovation'].value_counts()
Out[101]:
精装    11345
简装     8497
其他     3239
毛坯      576
南北       20
Name: Renovation, dtype: int64

发现在Renovation变量上多了“南北”这种异常数据,删除掉

In [105]: df= df.loc[(df['Renovation'] != '南北')]

In [106]: df['Renovation'].value_counts()
Out[106]:
精装    11345
简装     8497
其他     3239
毛坯      576
Name: Renovation, dtype: int64

检查过后已经没有任何异常数据和空缺值了。

总结

  • 最大的感触是还是得使用个编辑器,否则一不小心改错数据后又得重头再来
  • 检查数据的过程中有很多异常数据会隐藏的很深,光查看概览是不够的还需要去查看变量的统计
  • 有些数据是可以通过其他数据来做填充,如果出现大量数据空缺的情况尽量优先考虑填充而不是清除