1哑变量处理
也叫独热编码,英文:One-hot Encoding。可将任意离散型数据变为0-1数值。
import pandas as pd
df = pd.DataFrame({'性别':['男','女','男'],
'学历':['本科','硕士','本科'],
'民族':['汉族','仫佬族','维吾尔族']})
print(df)
| 学历 | 性别 | 民族 |
0 |
本科 |
男 |
汉族 |
1 |
硕士 |
女 |
仫佬族 |
2 |
本科 |
男 |
维吾尔族 |
哑变量函数:
pd.get_dummies(data, prefix=None, prefixsep='', dummy_na=False, columns=None, sparse=False, drop_first=False)
- data:进行哑变量处理的数据,无默认,不可省略
- prefix:前缀字符串
- prefixsep:连接字符串,默认为''
- dummy_na:表示是否将缺失值单独作为一类,默认为False,表示不将缺失值单独作为一类。
- columns:表示进行哑变量处理的列,仅接收list,默认所有的类别型的列。
- drop_first:表示是否剔除第一种类型,默认为False,表示不剔除。
# 初步简单调用
pd.get_dummies(df)
| 学历_本科 | 学历_硕士 | 性别_女 | 性别_男 | 民族_仫佬族 | 民族_汉族 | 民族_维吾尔族 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
2 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
# 修改column
pd.get_dummies(df, prefix = 'x')
| x_本科 | x_硕士 | x_女 | x_男 | x_仫佬族 | x_汉族 | x_维吾尔族 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
2 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
# 修改连接符_和选择进行哑变量的列
pd.get_dummies(df, prefix_sep=':', columns=['学历'])
| 性别 | 民族 | 学历:本科 | 学历:硕士 |
0 |
男 |
汉族 |
1 |
0 |
1 |
女 |
仫佬族 |
0 |
1 |
2 |
男 |
维吾尔族 |
1 |
0 |
# 是否显示第一类
# 例如性别非男即女,所以只需一列便可说明
pd.get_dummies(df, prefix_sep=':', drop_first=True)
| 学历:硕士 | 性别:男 | 民族:汉族 | 民族:维吾尔族 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
2 |
0 |
1 |
0 |
1 |
2离散化
很多时候,我们用的某些算法(如:ID3决策树,Apriori算法,Kmeans算法等)都要求数据是离散的,包括上边讲到的哑变量处理,所以我们一般还需要先对其进行连续型数据的离散化。
离散化函数:
pd.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)
- x:表示进行离散化的数据,只能是单独的某一列,或者Series。无默认,不可省略。
- bins:表示离散化后类别的数目。无默认,不可省略。
- right:是否包含最右边。bool,默认为True。
- labels:表示离散化后各个类别的标签,默认使用区间。
- retbins:是否返回bins。bool,默认为False。
- precision:bins的精度。int,默认为3。
- include_lowest:第一个左区间是否包含。bool,默认为False。(易引起ValueError或删除非唯一)
# 先输出连续型数据看看先
lsh = pd.DataFrame({'年龄':[18,16,15,17,19,28,80,55,36,43,12,23],
'身高':[180,160,150,170,170,153,165,155,162,170,120,185]})
print(lsh)
| 年龄 | 身高 |
0 |
18 |
180 |
1 |
16 |
160 |
2 |
15 |
150 |
3 |
17 |
170 |
4 |
19 |
170 |
5 |
28 |
153 |
6 |
80 |
165 |
7 |
55 |
155 |
8 |
36 |
162 |
9 |
43 |
170 |
10 |
12 |
120 |
11 |
23 |
185 |
2.1等宽离散化
pd.cut(lsh['年龄'], bins=5, labels=['青少年','而立','不惑','耳顺','耄耋'])
0 青少年
1 青少年
2 青少年
3 青少年
4 青少年
5 而立
6 耄耋
7 耳顺
8 而立
9 不惑
10 青少年
11 青少年
Name: 年龄, dtype: category
Categories (5, object): [青少年 < 而立 < 不惑 < 耳顺 < 耄耋]
pd.cut(lsh['年龄'], bins=5, precision=4, retbins=True)
(0 (11.932, 25.6]
1 (11.932, 25.6]
2 (11.932, 25.6]
3 (11.932, 25.6]
4 (11.932, 25.6]
5 (25.6, 39.2]
6 (66.4, 80.0]
7 (52.8, 66.4]
8 (25.6, 39.2]
9 (39.2, 52.8]
10 (11.932, 25.6]
11 (11.932, 25.6]
Name: 年龄, dtype: category
Categories (5, interval[float64]): [(11.932, 25.6] < (25.6, 39.2] < (39.2, 52.8] < (52.8, 66.4] < (66.4, 80.0]],
array([11.932, 25.6 , 39.2 , 52.8 , 66.4 , 80. ]))
pd.cut(lsh['年龄'], bins=5, include_lowest=True)
0 (11.931000000000001, 25.6]
1 (11.931000000000001, 25.6]
2 (11.931000000000001, 25.6]
3 (11.931000000000001, 25.6]
4 (11.931000000000001, 25.6]
5 (25.6, 39.2]
6 (66.4, 80.0]
7 (52.8, 66.4]
8 (25.6, 39.2]
9 (39.2, 52.8]
10 (11.931000000000001, 25.6]
11 (11.931000000000001, 25.6]
Name: 年龄, dtype: category
Categories (5, interval[float64]): [(11.931000000000001, 25.6] < (25.6, 39.2] < (39.2, 52.8] < (52.8, 66.4] < (66.4, 80.0]]
2.2等频离散化
# 没现成,只能自定义函数
def Frequency_cut(data, k):
'''
data:进行离散化的数据,只能是单独的某一列,或者Series
k:分为几组,int型,无默认
'''
import numpy as np
# 算出data的分位数
w = data.quantile(np.arrange(0, 1+1.0/k, 1.0/k))
# 将各分位数作为区间边界
data = pd.cut(data, w, include_lowest=True)
return data
# 试运行,结果如下
Frequency_cut(lsh['身高'], 2)
0 (163.5, 185.0]
1 (119.999, 163.5]
2 (119.999, 163.5]
3 (163.5, 185.0]
4 (163.5, 185.0]
5 (119.999, 163.5]
6 (163.5, 185.0]
7 (119.999, 163.5]
8 (119.999, 163.5]
9 (163.5, 185.0]
10 (119.999, 163.5]
11 (163.5, 185.0]
Name: 身高, dtype: category
Categories (2, interval[float64]): [(119.999, 163.5] < (163.5, 185.0]]
2.3使用聚类模型进行离散化
def Kmeans_cut(data, k):
from sklearn.cluster import KMeans #引入KMeans
# 建立模型
kmodel = KMeans(n_clusters=k, n_jobs=4) # KMeans函数在下文有讲
# 训练模型
kmodel.fit(data.reshape((len(data), 1))) # 重塑data
# 输出聚类中心并排序
c = pd.DataFrame(kmodel.cluster_centers_).sort_values(0) # 0纵1横
# 相邻两项求中点,加上首末,作为边界点
w = pd.rolling_mean(c, 2).iloc[1:] # 问题:rooling_mean的使用
w = [0] + list(w[0]) + [data.max()] # 问题:为什么是w[0]
data = pd.cut(data, w)
return data
# 试一试,美滋滋
Kmeans_cut(lsh['年龄'], 5)
0 (0.0, 20.833]
1 (0.0, 20.833]
2 (0.0, 20.833]
3 (0.0, 20.833]
4 (0.0, 20.833]
5 (20.833, 32.5]
6 (67.5, 80.0]
7 (47.25, 67.5]
8 (32.5, 47.25]
9 (32.5, 47.25]
10 (0.0, 20.833]
11 (20.833, 32.5]
Name: 年龄, dtype: category
Categories (5, interval[float64]): [(0.0, 20.833] < (20.833, 32.5] < (32.5, 47.25] < (47.25, 67.5] < (67.5, 80.0]]
Last,简略讲一下KMeans函数。
# 有赋值的即为有默认值
def __init__(self, n_clusters=8, init='k-means++', n_init=10, max_iter=300, tol=1e-4, precompute_distances='auto', verbose=0, random_state=None, copy_x=True, n_jobs=1):
输入参数:
- n_clusters:要分成几类,即生成的质心数,int;
- init:初始化质心,function或array;
- n_init:设置初始化质心种子的次数,返回最好的一次,int;
- max_iter:每次迭代的最大次数,int;
- tol:容忍的最小误差,当误差小于tol时就会退出迭代,float;
- precompute_distances:权衡空间和时间,True时全放内存,auto时若样本小于12e6则True,其他相反,bool;
- verbose:是否输出详细信息,bool;
- random_state:随机生成器的种子,和初始化质心有关,int或numpy;
- copy_x:是否copy输入数据,为了不修改输入的数据,bool;(sklearn很多地方都有这个参数)
- n_jobs:并行数,即进程数量,与CPU有关,int。
输出参数:
- label_:每个类的标签;
- cluster_centers:每个类的中心,也叫聚类中心。(例子请看上边代码)