import pandas as pd
data = pd.read_csv(r"E:\机器学习\sklearn学习\数据\Narrativedata.csv",index_col=0)
#index_col=0 告诉它索引列是第0列首列
data.head()
#Embarked舱门
data.info() #查看缺失情况
sklearn.impute.SimpleImputer (missing_values=nan, strategy=’mean’, fill_value=None, verbose=0,copy=True)
#填补年龄
Age = data.loc[:,"Age"].values.reshape(-1,1) #sklearn当中特征矩阵必须是二维
#data.loc[:,"Age"]---由索引列+Age列的值组成
#data.loc[:,"Age"].values 取出Age列的值
data.loc[:,"Age"].values.shape
#输出(891,)----只有一个数字,是一维的。即输出的数据只有一个方括号
data.loc[:,"Age"].values.reshape(-1,1).shape
#输出(891,1)----是二维的。即输出的数据有两个方括号
#sklearn当中特征矩阵必须是二维
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer() #实例化,默认均值填补
imp_median = SimpleImputer(strategy="median") #用中位数填补
imp_0 = SimpleImputer(strategy="constant",fill_value=0) #用0填补
imp_mean = imp_mean.fit_transform(Age)
#fit_transform一步完成调取结果
imp_median = imp_median.fit_transform(Age)
imp_0 = imp_0.fit_transform(Age)
imp_mean[:20] #均值29.699填补的
imp_median[:20] #中位数28填补的
imp_0[:20] #0填补的
#在这里我们使用中位数填补Age
data.loc[:,"Age"] = imp_median
data.info()
#Age填补完成
#使用众数填补Embarked
Embarked = data.loc[:,"Embarked"].values.reshape(-1,1)
imp_mode = SimpleImputer(strategy = "most_frequent")
data.loc[:,"Embarked"] = imp_mode.fit_transform(Embarked)
data.info()
#BONUS:用Pandas和Numpy进行填补其实更加简单
import pandas as pd
data_ = pd.read_csv(r"E:\机器学习\sklearn学习\数据\Narrativedata.csv",index_col=0)
data_.head()
data_.loc[:,"Age"] = data_.loc[:,"Age"].fillna(data_.loc[:,"Age"].median())
#.fillna 在DataFrame里面直接进行填补 -- 填充列.fillna(要填的值)
data_.info()
data_.dropna(axis=0,inplace=True)
#.dropna(axis=0)删除所有有缺失值的行,.dropna(axis=1)删除所有有缺失值的列
#参数inplace,为True表示在原数据集上进行修改,为False表示生成一个复制对象,不修改原数据,默认False
data_.info()
#填充完成
编码,即,将文字型数据转换为数值型
LabelEncoder :标签专用,能够将分类转换为分类数值
#LabelEncoder :标签专用,能够将分类转换为分类数值
from sklearn.preprocessing import LabelEncoder
y = data_.iloc[:,-1] #要输入的是标签,不是特征矩阵,所以允许一维
le = LabelEncoder() #实例化
le = le.fit(y) #导入数据
label = le.transform(y) #transform接口调取结果
le.classes_ #属性.classes_查看标签中究竟有多少类别
#三个类
label #结果处理后显示,0,1,2
le.fit_transform(y) #也可以直接fit_transform一步到位
#等价于上面三步
le.inverse_transform(label) #使用inverse_transform可以逆转
#重新完整的代码,应该为:
#如果不需要教学展示的话我会这么写:
from sklearn.preprocessing import LabelEncoder
data.iloc[:,-1] = LabelEncoder().fit_transform(data.iloc[:,-1])
OrdinalEncoder :特征专用,能够将分类转换为分类数值
特征矩阵,就强调不能导入一维数组了
from sklearn.preprocessing import OrdinalEncoder
#接口categories_对应LabelEncoder的接口classes_,一模一样的功能
data_ = data.copy() #保护原本data不受覆盖
data_.head()
OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_ #一步到位
#categories_作用同classes_ ,查看类别
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
data_.head() #性别0、1 舱门0,1,2 存活情况0,1,2
OneHotEncoder:独热编码,创建哑变量
考三种不同性质的分类数据:
1) 舱门(S,C,Q)
三种取值S,C,Q是相互独立的,彼此之间完全没有联系,表达的是S≠C≠Q的概念。这是名义变量。
2) 学历(小学,初中,高中)
三种取值不是完全独立的,我们可以明显看出,在性质上可以有高中>初中>小学这样的联系,学历有高低,但是学历取值之间却不是可以计算的,我们不能说小学 + 某个取值 = 初中。这是有序变量。
3) 体重(>45kg,>90kg,>135kg)
各个取值之间有联系,且是可以互相计算的,比如120kg - 45kg = 90kg,分类之间可以通过数学计算互相转换。有距变量
然而在对特征进行编码的时候,这三种分类数据都会被我们转换为[0,1,2],这三个数字在算法看来,是连续且可以计算的,这三个数字相互不等,有大小,并且有着可以相加相乘的联系。
所以算法会把舱门,学历这样的分类特征,都误会成是体重这样的分类特征。
这是说,我们把分类转换成数字的时候,忽略了数字中自带的数学性质,所以给算法传达了一些不准确的信息,而这会影响我们的建模。
名义变量,使用哑变量的方式来处理,才能够尽量向算法传达最准确的信息
舱门—名义变量–哑变量–独热编码OneHotEncoder
体重—有距变量–编码
data.head()
from sklearn.preprocessing import OneHotEncoder
X = data.iloc[:,1:-1]
enc = OneHotEncoder(categories='auto').fit(X) #实例化
result = enc.transform(X).toarray() #toarray()转化成数组
result
#sex变两列 ,仓号变3列
#依然可以直接一步到位,但为了给大家展示模型属性,所以还是写成了三步
OneHotEncoder(categories='auto').fit_transform(X).toarray()
#依然可以还原
pd.DataFrame(enc.inverse_transform(result))
#还原成两列特征
enc.get_feature_names()
#给出每个哑变量对应的原本类值
result
result.shape
#把生成的5列哑变量拼接data上去
#axis=1,表示跨行进行合并,也就是将两表左右相连,如果是axis=0,就是将量表上下相连
newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
newdata.head()
newdata.drop(["Sex","Embarked"],axis=1,inplace=True) #删除原本两特征列
newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
#重命名特征名字
newdata.head()
标签列:是否存活—用0,1表示
把标签列设置成哑变量很少,因为用的分类算法,就已经把标签当分类型数值了
对分类数据的处理到此结束
二值化:
根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0。
二值化是对文本计数数据的常见操作,分析人员可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如,使用贝叶斯设置中的伯努利分布建模)。
#将年龄二值化
data_2 = data.copy()
from sklearn.preprocessing import Binarizer
X = data_2.iloc[:,0].values.reshape(-1,1) #类为特征专用,所以不能使用一维数组
transformer = Binarizer(threshold=30).fit_transform(X)
transformer #分为了小于30岁的与大于等于30的
data_2.iloc[:,0]=transformer #替换原本年龄列
将连续型变量划分为分类变量的类
n_bins 每个特征分箱的个数,默认为5 encode 编码方式,默认onehot strategy 定义箱宽的方式,默认quantite(uniform 等宽分箱;quantitle 等位分箱 ;kmeans聚类分箱)
from sklearn.preprocessing import KBinsDiscretizer
X = data.iloc[:,0].values.reshape(-1,1)
est = KBinsDiscretizer(n_bins=3,encode='ordinal',strategy='uniform')
est.fit_transform(X)
#查看转换后分的箱;变成了一列中的三箱
set(est.fit_transform(X).ravel())
est = KBinsDiscretizer(n_bins=3,encode='onehot',strategy='uniform')
#查看转换后分的箱;变成了哑变量
est.fit_transform(X).ravel()