数据挖掘06--特征变换(一)

目录

A.数值型(连续型)

B.离散型

B.1分类数据(categorical or nominal data)

B.1.1二分类型*

B.1.2多分类*

B.2 顺序数据(Ordinal data)

顺序型

1. 特征数值化(分类型特征转数值)

1.1. df.replace方法 字符串替换为数值

1.2. sklearn中专有模块LabelEncoder

1.3. 项目案例

2. 特征二值化

2.1. np.where函数完成阈值判断和赋值

 2.2. 利用sklearn提供二值化模块Binarizer实现二值化

 动手练习

 3. OneHot编码

3.1. pd.get_dummies生成哑变量

3.2. sklearn中的OneHotEncoder

动手练习:

4. 数据变换 

4.1. 多项式变换

4.2. Box_Cox变换


特征的类型由其所有值的集合决定,通常有如下几种。

A.数值型(连续型)

  • 特征的值如果是整数或浮点数,那么这类特征就是"数值型"的,也可以分别称为整数型特征或浮点数型特征。

B.离散型

  • 特征取值数量有限,每个值表示一种状态、类别,不能进行计算。
  • 特征的值如果是字符串,这些值不能直接输入机器学习算法中,通常要经过转换,例如使用 OneHot 编码实现转换。
  • 分类型特征的值如果是数字,这些值并不是定量的,计算值、中位数等没有什么意义。

B.1分类数据(categorical or nominal data)

  • 是只能归于某一类别的非数字型数据,它是对事物进行分类的结果,数据表现为类别,是用文字来描述的。例如:
  • 例如,“性别”的值一般是"男"或者"女",即使分别用1和0表示,也不意味有某种顺序。
  • 再如,"职业"的值可能是"商、农、工、士"中的些值没有顺序(也没有高低贵贱之分)。

B.1.1二分类型*

  • 特征的值如果只有两种状态,比如0或1,那么这类特征就是"二值型的,显然它也是分类型的。二值型特征也可以称为"二元型特征"或者"布尔型特征"。
  • 有的二值型特征的两个状态是等价的,例如在性别中,用0表示女,也可以用0表示男,这两个状态并不存在不同的权重。与之不同的是,另外-类二值型特征,其不同状态表示不同的重要程度,通常用1表示更重要的状态,用0表示另一种状态。例如,对普通大众的HTV检验,呈阳性的用1表示,呈阴性的用0表示——就正常社会群体而言,携带HIV病毒的人数是稀少的。在如此得到的数据中,0的数量就比较多,这样的数据称为"稀疏的"。

B.1.2多分类*

  • 特征的值如果只有多种状态,"职业"的值可能是"商、农、工、士"中的些值没有顺序(也没有高低贵贱之分)。

B.2 顺序数据(Ordinal data)

  • 是只能归于某一有序类别的非数字型数据。顺序数据虽然也是类别,但这些类别是有序的。

顺序型

对于前面的多分类型特征和二值型特征的值,其排序都没有意义。如果有像"职称"这样的特征,其值分别为"讲师"、"副教授"、"教授",从某个角度讲,它们就具有顺序,这样的特征称为顺序型特征。顺序型特征的值可以是数字。

  • *例:

  • (1)将产品分为一等品、二等品、三等品、次品等;

  • (2)考试成绩可以分为优、良、中、及格、不及格等;

  • (3)一个人的受教育程度可以分为小学、初中、高中、大学及以上

  • (4)一个人对某一事物的态度可以分为非常同意、同意、保持中立、不同意、非常不同意,等,问卷调查(李克特量表常使用)

  • 此外,顺序型特征还可以通过对连续型特征离散化而得到。比如,学生的考试成绩按照下面的原则划分等级∶A(90~100分)B(75~<90分)人C(60~<75分)、D(45~<60分)、E(45分以下)。

  •  之所以要分辨不同类型的特征,是因为机器学习算法对特征的类型会有所偏好,不合适的就要通过特征变换,以适合算法对数据的要求。并且,通过特征变换之后,数据的可解释性可得到提高。

1. 特征数值化(分类型特征转数值)

1.1. df.replace方法 字符串替换为数值

#将数据集中的Y、N替换为数字,比如用1替换Y,用0替换N,

df1=df.replace({"N": 0, 'Y': 1})

df1

1.2. sklearn中专有模块LabelEncoder

字符串转数值 数值

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

le.fit_transform(df['hypertension']) #包括了训练又包含了转换

#实例化LabelEncoder,得到了一个实现特征数值化的模型实例,用它训练特征中的数据,即可得到其中的枚举值。

#特征"hypertension"是分类或者二值型的,le实例能自动从0开始,将每个值用整数替换。

1.3. 项目案例

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()    # ①
le.fit(['white', 'green', 'red', 'green', 'white'])    # ②
le.classes_    # ③
>>>
ray(['green', 'red', 'white'], dtype='<U5')

①创建了模型;②用参数中的数据进行训练,创建了能够对含有“white”、“green”、“red”三个值的特征进行数值化的模型le;③显示自动分类的结果。从结果来看,三个字符串依次对应0、1、2。

le.transform(["green", 'green', 'green', 'white'])    # ④
#使用②训练的模型对另外一批数据(参数内显示的数据)进行转换,得到了所示的结果。
#前面所使用过的fit_transform相当于②和④的合并。
>>>
array([0, 0, 0, 2])

#如果④中出现了超出所得分类的参数,就会报错了

le.transform(["green", 'green', 'green', 'blue'])

2. 特征二值化

不论是连续型特征还是离散型特征,都可以进行二值化变换,其通常则是∶

2.1. np.where函数完成阈值判断和赋值

#任务:以平均值为阈值,对特征“Exposed day”进行二值化
import numpy as np
pm25['bdays'] = np.where(pm25["Exposed days"] > pm25["Exposed days"].mean(), 1, 0)
pm25.sample(5)
#新增加的特征"bdays"是对"Exposed days"二值化之后所得到的二值型特征。
#用np.where 函数完成了阈值的判断和相应赋值。#
#print(type(pm25["Exposed days"].mean()))

 2.2. 利用sklearn提供二值化模块Binarizer实现二值化

#可以使用scikit-learn提供的二值化模块 Binarizer 实现特征二值化
from sklearn.preprocessing import Binarizer
bn = Binarizer(threshold=pm25["Exposed days"].mean())    # ①
result = bn.fit_transform(pm25[["Exposed days"]])   # ②
#参数是 pm25([“[Exposed days"]]),旨在得到一个形状为一列的 DataFrame对象
pm25['sk-bdays'] = result
pm25.sample(10)

binarzne的函数

#另外,与模块Biaizer 等效的还有一个 名为binarzne的函数。
from sklearn.preprocessing import binarize
fbin = binarize(pm25[['Exposed days']], threshold=pm25['Exposed days'].mean())
fbin[[1, 50, 100, 150, 200]]
#在 scikit-leam的模块中,有一些模块类似于Binarizer,
#会对应一个同名的函数,在使用的时候,这两者等效。
>>>
array([[0],
       [0],
       [0],
       [1],
       [1]])
  • np.random.normal(loc=0.0, scale=1.0, size=None)
  • 参数解释:
  • loc(float):此概率分布的均值(对应着整个分布的中心centre
  • scale(float):此概率分布的标准差(对应于分布的宽度,scale越大,图形越矮胖;scale越小,图形越瘦高)
  • size(int or tuple of ints):输出的shape,默认为None,只输出一个值

 动手练习

import datetime
print(pd.read_csv("mydata/marathon.csv").head())
def convert_time(s):
    h,m,s = map(int, s.split(":"))
    return datetime.timedelta(hours=h, minutes=m, seconds=s)
marathon = pd.read_csv("mydata/marathon.csv",
                      converters={"split":convert_time, 
                                  "final":convert_time})
marathon.head(3)

marathon['split'] = marathon['split'].astype(int) * 1e-9
marathon['final'] = marathon['final'].astype(int) * 1e-9
marathon.head()

 

marathon['frac'] = 1 - 2 * marathon['split'] / marathon["final"]
marathon.head()

 

marathon['split_frac'] = np.where(marathon['frac']>0, 0, 1)
marathon.sample(10)

 3. OneHot编码

import pandas as pd
g = pd.DataFrame({"gender": ["man", 'woman', 'woman', 'man', 'woman']})
g

  

特征"gender"的值除了man就是 woman,按照前面对特征类内述.它是分类型特征,也是二值型特征。并且,经用"数值化"的方式处理过这种类型的特征,但是数值化会带来原本没有的”大小关系”。 为了避免这种“副作用”的出现,换一种处理方式

3.1. pd.get_dummies生成哑变量

pd.get_dummies(g)

自动生成了两个新特征

dummies 英 [ˈdʌmiz] 美 [ˈdʌmiz] n. (尤指缝制或陈列服装用的)人体模型;仿制品;仿造物;笨蛋;蠢货

pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)

其作用是将分类型特征转化为“虚拟变量”(也译为“哑变量”)

  • prefix:str, list of str, 或 dict of str, 默认为 None 用于追加DataFrame列名称的字符串。

  • prefix_sep:str, 默认为 ‘_’如果附加前缀,则使用分隔符/分隔符。或者像这样传递列表或字典prefix。

  • dummy_na:bool, 默认为 False 忽略False NaN。

  • columns:list-like, 默认为 None 要编码的DataFrame中的列名。如果columns为None,则所有具有的列object或者categorydtype将被转换。

  • sparse:bool, 默认为 False

  • dummy-encoded列是否应由a支持SparseArray(True)或常规NumPy数组(False)。

** dropfirst:bool, 默认为 False* 是否通过删除第一个级别从k个分类级别中获取k-1个虚拟对象

pd.get_dummies(g,prefix="1",prefix_sep="_")

persons = pd.DataFrame({"name":["Newton", "Andrew Ng", "Jodan", "Bill Gates"], 
                        'color':['white', 'yellow', 'black', 'white']})
persons

 

df_dum = pd.get_dummies(persons['color'], drop_first=True)   
persons.merge(df_dum, left_index=True, right_index=True)# 按索引值进行连接

#三个类别也一样创建虚拟变量,并且还是要去掉一个冗余特征

 

3.2. sklearn中的OneHotEncoder

from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
features = ohe.fit_transform(persons[['color']])
#features
print(features)
features.toarray()

 

data=pd.DataFrame(features.toarray())
data

 

 OneHotEncoder模块的使用方法与前面已介绍过的scikit-leam中其他块的使用方法一样,不再赘述。但是,在OneHotEncoder模块中,没有提类似get_dummies中的参数drop_first,要去掉一个虚拟变量,只能用Numpy的数组切片操作。

features.toarray()[:, 1:]

动手练习:

df = pd.DataFrame({
    "color": ['green', 'red', 'blue', 'red'],
    "size": ['M', 'L', 'XL', 'L'],
    "price": [29.9, 69.9, 99.9, 59.9],
    "classlabel": ['class1', 'class2', 'class1', 'class1']
})
df
df["classlabel"].unique()
>>>
array(['class1', 'class2'], dtype=object)
# 第1题 对'classlabel'进行onehot编码
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
cl = ohe.fit_transform(df[['classlabel']])
cl.toarray()
fs_two=pd.DataFrame(cl.toarray()[:,1:],columns=["classlabel_"])
fs_two
df = pd.concat([df, fs_two], axis=1)
df

# 第2题
df = pd.read_csv("/home/aistudio/data/data170095/breast-cancer.data", header=None).iloc[:, 1:]
dataset = df.values
X = dataset[:, 0:8]
X = X.astype(str)
Y = dataset[:, 8]
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
import numpy as np
encoded_x = None
for i in range(0, X.shape[1]):
    label_encoder = LabelEncoder()    # 数值化
    feature = label_encoder.fit_transform(X[:,i])
    feature = feature.reshape(X.shape[0], 1)
    onehot_encoder = OneHotEncoder(sparse=False)    # OneHot编码
    feature = onehot_encoder.fit_transform(feature)
    if encoded_x is None:
        encoded_x = feature
    else:
        encoded_x = np.concatenate((encoded_x, feature), axis=1)
print("X shape: : ", encoded_x.shape)
X shape: :  (286, 41)
label_encoder = LabelEncoder()
label_encoder = label_encoder.fit(Y)
label_encoded_y = label_encoder.transform(Y)
label_encoded_y

4. 数据变换 

4.1. 多项式变换

import numpy as np
X = np.arange(6).reshape(3, 2)
X
>>>
array([[0, 1],
       [2, 3],
       [4, 5]])
  • 这个简单的数据包含两个变量(列、特征),分别用x1、x2表示,
  • 如果要用这两个变量创建一个最高项为2的多项式,即
  • 1+x1+x2+x1²+x1x2+x2² 式①
  • 用此多项式的各项对原数据进行计算,并将结果作为新特征,这就是所谓的“多项式变换”。
from sklearn.preprocessing import PolynomialFeatures    # ③
poly = PolynomialFeatures(2)    # ④
poly.fit_transform(X)
>>>
array([[ 1.,  0.,  1.,  0.,  0.,  1.],
       [ 1.,  2.,  3.,  4.,  6.,  9.],
       [ 1.,  4.,  5., 16., 20., 25.]])

引入了scikit-leam的多项式模型PolynomialFeatures,④创建此模型实例,其中的参数2表示创建最高项为2的多项式,即如同“式①”那样。4.1的结果为根据“式①”各项计算的所得内容。

4.2. Box_Cox变换

dc_data = pd.read_csv('/home/aistudio/data/data170095/sample_data.csv')
#数据进行处理之前,先观察它的分布
%matplotlib inline
import matplotlib.pyplot as plt
h = plt.hist(dc_data['AIR_TIME'], bins=100)

#array和asarray都可以将结构数据转化为ndarray,但是主要区别就是当数据源是ndarray时,
#array仍然会copy出一个副本,占用新的内存,但asarray不会。

#dc_data【'AIR_TIME】中的数据不是标准的正态分布,下面就对它进行变换
from scipy import stats
transform = np.asarray(dc_data[['AIR_TIME']].values)   
print(transform)
dft = stats.boxcox(transform)[0]   # ⑤
hbc = plt.hist(dft, bins=100)

  • scipy是一个专门用于科学计算的第三方库,它提供Box-Cox变换函数,即可实现Box-Cox变换。
  • 再绘制直方图看看效果,操作让数据更趋于"正态分布"。
  • 除在scipy提供了实现Box-Cox变换的函数外,在scikit-lcam中也有相应函数供使用。

Box-Cox属于广义幂变换,sklearn.preprocessing中的power_transform函数的命名也符合了这种说法。

#Box-Cox属于广义幂变换,sklearn.preprocessing中的power_transform函数的命名也符合了这种说法。
#利用power_transform函数,除了可以实现Box-Cox变换
from sklearn.preprocessing import power_transform
dft2 = power_transform(dc_data[['AIR_TIME']], method='box-cox')    # ⑥
hbcs = plt.hist(dft2, bins=100)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值