数据清理
由上一阶段的学习,通过info方法我们查看到了数据集的简单描述。
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20640 entries, 0 to 20639
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 longitude 20640 non-null float64
1 latitude 20640 non-null float64
2 housing_median_age 20640 non-null int64
3 total_rooms 20640 non-null int64
4 total_bedrooms 20433 non-null float64
5 population 20640 non-null int64
6 households 20640 non-null int64
7 median_income 20640 non-null float64
8 median_house_value 20640 non-null int64
9 ocean_proximity 20640 non-null object
dtypes: float64(4), int64(5), object(1)
memory usage: 1.6+ MB
我们发现total_bedrooms这个属性其实是缺少数据的,翻开csv文件也
解决它的三个方式:
- 放弃这些相应的地区
- 放弃这个属性
- 将缺失值设置为某个值(0、平均数或者中位数都可以)
通过DataFrame的dropna()、drop()、fillna()方法,可以轻松完成这些操作:
我们先来看一下housing
>>> housing
longitude latitude ... median_house_value ocean_proximity
0 -122.23 37.88 ... 452600 NEAR BAY
1 -122.22 37.86 ... 358500 NEAR BAY
2 -122.24 37.85 ... 352100 NEAR BAY
3 -122.25 37.85 ... 341300 NEAR BAY
4 -122.25 37.85 ... 342200 NEAR BAY
... ... ... ... ...
20635 -121.09 39.48 ... 78100 INLAND
20636 -121.21 39.49 ... 77100 INLAND
20637 -121.22 39.43 ... 92300 INLAND
20638 -121.32 39.43 ... 84700 INLAND
20639 -121.24 39.37 ... 89400 INLAND
[20640 rows x 10 columns]
1.放弃这些相应的地区
>>> housing.dropna(subset=['total_bedrooms']) #option 1
[20433 rows x 10 columns]
2.放弃这个属性
>>> housing.drop('total_bedrooms',axis=1)
[20640 rows x 9 columns]
3.将缺失的值设置为某个值(0、平均数或中位数)
>>> median = housing['total_bedrooms'].median()
housing['total_bedrooms'].fillna(median)
Scikit-Learn imputer
Scikit-Learn提供了imputer来处理缺失值
from sklearn.preprocessing import Imputer
imputer = Imputer(strategy='median')
这里代码发现运行不出来,用的anaconda,这里参考了一下
sklearn.preprocessing里缺失Imputer函数
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy = "mean")
housing_num = housing.drop('ocean_proximity', axis = 1) # 因为中位数只能在数值属性操作 ocean_proximity是object类型
imputer.fit(housing_num)
X = imputer.fit_transform(housing_num)
housing_tr = pd.DataFrame(X, columns= housing_num.columns)
>>> housing_tr
longitude latitude ... median_income median_house_value
0 -122.23 37.88 ... 8.3252 452600.0
1 -122.22 37.86 ... 8.3014 358500.0
2 -122.24 37.85 ... 7.2574 352100.0
3 -122.25 37.85 ... 5.6431 341300.0
4 -122.25 37.85 ... 3.8462 342200.0
... ... ... ... ...
20635 -121.09 39.48 ... 1.5603 78100.0
20636 -121.21 39.49 ... 2.5568 77100.0
20637 -121.22 39.43 ... 1.7000 92300.0
20638 -121.32 39.43 ... 1.8672 84700.0
20639 -121.24 39.37 ... 2.3886 89400.0
[20640 rows x 9 columns]
文本分类
之前排除了分类属性ocean_proximity,因为其是一个文本属性,无法计算它的中位数值。大部分机器学习算法更易于与数字打交道,所以可以先将这些文本标签转化为数字。
Scikit-Learn为这一类任务提供了一个转换器LabelEncoder:
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
housing_cat=housing['ocean_proximity']
housing_cat_encoded=encoder.fit_transform(housing_cat)
>>> housing_cat_encoded
array([3, 3, 3, ..., 1, 1, 1])
现在可以使用classes_属性来查看这个编码器的映射< 对应为 , 对应为 >
>>> encoder.classes_
array(['<1H OCEAN', 'INLAND', 'ISLAND', 'NEAR BAY', 'NEAR OCEAN'], dtype=object)
这这种代表方式可能类别0和类别4之间就比类别0和类别1之间的相似度更高
常见的解决方案是给每个类别创建一个二进制的属性,独热编码
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder()
housing_cat_1hot=encoder.fit_transform(housing_cat_encoded.reshape(-1,1))
>>> housing_cat_1hot
<20640x5 sparse matrix of type '<class 'numpy.float64'>'
with 20640 stored elements in Compressed Sparse Row format>'
>>> housing_cat_1hot.toarray()
array([[0., 0., 0., 1., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 1., 0.],
...,
[0., 1., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 1., 0., 0., 0.]])
使用LabelBinarizer类可以一次性完成两个转换(从文本类别转化为整数类别,再从整数类别转换为独热向量):
from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(housing_cat)
>>> housing_cat_1hot
array([[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0],
...,
[0, 1, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 1, 0, 0, 0]])
学习《机器学习实战》,用作笔记。