一、数据离散化
1、所谓离散化,就是把无限空间中的有限个体映射到一个有限的空间中。
2、数据离散化大多针对连续数据进行,处理后数据值域分布将从连续属性变为离散属性。
3、数据离散化在很多情况下也有针对已经离散化的数据,大多是因为这些离散化数据本身划分过于复制和琐碎,甚至不符合业务逻辑。
二、数据离散化的方法
2.1针对时间数据离散化
1、在带时间的数据集中,时间可作为行记录序列,也可作为列记录的数据特征。
2、时间数据离散化操作2类:
- 1天中的时间离散,时间戳转为秒,分钟,小时或上午
- 日颗粒以上的,日期转化为周数,周几,月,工作日或休息日,季度,年等
3、常使用方法:利用dt访问器对时间数据进行操作
# 设置cell多行输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默认为'last'
# 导入相关库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import warnings
warnings.filterwarnings('ignore')
os.chdir(r'E:\python_learn\data\python_book_v2\chapter3')
# 导入数据
file_name = 'data7.txt'
df = pd.read_table(file_name,names=['id','amount','income','datetime','age'])
print(df.head())
id amount income datetime age
0 15093 1390 10.40 2017-04-30 19:24:13 0-10
1 15062 4024 4.68 2017-04-27 22:44:59 70-80
2 15028 6359 3.84 2017-04-27 10:07:55 40-50
3 15012 7759 3.70 2017-04-04 07:28:18 30-40
4 15021 331 4.25 2017-04-08 11:14:00 70-80
# 缺失查看
df.isna().sum().sum()
0
# 数据结构查看
df['datetime'].dtypes
df['datetime'] = pd.to_datetime(df['datetime'])
dtype('O')
df.info()
RangeIndex: 100 entries, 0 to 99
Data columns (total 5 columns):
id 100 non-null int64
amount 100 non-null int64
income 100 non-null float64
datetime 100 non-null datetime64[ns]
age 100 non-null object
dtypes: datetime64[ns](1), float64(1), int64(2), object(1)
memory usage: 4.0+ KB
# 时间数据离散化 → 转为周几
df['weekday'] = df['datetime'].dt.weekday
print(df.head())
# 0 → 周一
# 6 → 周日
id amount income datetime age weekday
0 15093 1390 10.40 2017-04-30 19:24:13 0-10 6
1 15062 4024 4.68 2017-04-27 22:44:59 70-80 3
2 15028 6359 3.84 2017-04-27 10:07:55 40-50 3
3 15012 7759 3.70 2017-04-04 07:28:18 30-40 1
4 15021 331 4.25 2017-04-08 11:14:00 70-80 5
2.2针对多值离散数据的离散化
1、对多值离散化是指要进行离散化的数据本身不是数值型数据,而是分类或定序数据。如本次使用的数据集的age字段。
2、例如,用户收入变量的值原为10个区间,后因新需求,需要将其划分为4个区间,这时就需对原10个区间进行重新划分。
3、对多值离散化除了因需而变,还可能因为业务逻辑不符合或变更需要重新划分。
df['age'].unique()
len(df['age'].unique()) # 查看age字段的唯一值个数 →10个
array(['0-10', '70-80', '40-50', '30-40', '10-20', '20-30', '>90',
'50-60', '60-70', '80-90'], dtype=object)
10
# 将原来10个区间转换为3个区间 → 0-40,40-80,>80
dic = {'age':['0-10','10-20','20-30','30-40','40-50','50-60','60-70','70-80','80-90','>90'],
'age_new':['0-40','0-40','0-40','0-40','40-80','40-80','40-80','40-80','>80','>80']
}
age_new = pd.DataFrame(dic)
data = pd.merge(df,age_new,on='age')
data.head(10)
2.3针对连续数据离散化
1、针对连续数据离散化是离散化的主要应用操作。
2、连续数据离散化结果分为两类:
- 将连续数据划分为特定区间集合 → {0-10,10-20,20-30……}
- 将连续数据划分为特定类 → 1类、2类、3类
2.3.1连续数据离散化常用方法:
(1)等宽法(距离区间法)
等宽法(距离区间法) → pandas的cut方法
使用等距或自定义区间的方式进行离散化。即系将连续型变量的取值范围均匀划分成n等份,每份的间距相等。
如,年龄字段,将其划分为0-10岁为一组,10-20岁为一组……以此类推,其组距都为10;
特点:灵活且能满足自定义需求并能保持数据原有分布。
# pandas的cut方法对字段amount实现等宽划分
bins = [0,200,1000,5000,10000] # 自定义区间边界
data['amount_cut'] = pd.cut(data['amount'],bins) # 没设置labels参数
data['amount_cutLabel'] = pd.cut(data['amount'],bins,labels=['bad','medium','good','awesome']) # 设置labels参数
data.head()
# labels参数设置了就用标签代替上述区间
(2)等频法(频率区间法)
- 等频法(频率区间法): → pandas的qcut方法
以相同数量的记录放进每个区间,即系把观察点均匀分成n等份,每份包含的观察点数相同。
如,某杂志订户共有5万人,等频分段需要先把订户按订阅时间按顺序排列,排列好后可以按5000人一组,把全部订户均匀分为十段。
特点:数据会被均匀分布,各个区间的观察值相同,改变数据原有的分布状态。
data['amount_qcut'] = pd.qcut(data['amount'],q=4) # 按4份划分,每份数量相同
# 参数q表示,整数或分位数组成的数组,即要将数据分成几组
data.groupby(data['amount_qcut']).count()['amount_qcut'] # 查看每组的数量
(3)聚类法(基于聚类分析的方法)
- 聚类法(基于聚类分析的方法): → sklearn.cluster的K-Means方法
2个步骤:① 将连续属性的值用聚类算法(如K-Means算法)进行聚类;
② 将聚类得到的簇进行处理,合并到一个簇的连续属性值做同一标记。
但是,聚类分析的离散化方法也需要事先指定簇的个数,从而决定产生的区间数(类数)
→ sklearn.cluster的K-Means算法实现:
① 获得建模数据列
② 作为输入变量需要做形状转换,否则算法会认为输入数据只有1行
③ 创建KMwans模型并指定聚类数量,设置初始化随机种子固定值为0,否则每次聚类的结果很可能不一样
④ 使用fit_predict方法直接建模输出结果
# sklearn.cluster的K-Means方法实现
from sklearn.cluster import KMeans
amount = data['amount']
amount.shape # amount列原形状为1行数据
amount_shape = amount.values.reshape((amount.shape[0],1)) # reshape转换形状
amount_shape.shape # 转换形状后为(100,1) 100行*1列
model_kmeans = KMeans(n_clusters=4,random_state=0) # 创建Kmeans模型
# n_clusters=4,指定聚类数量
# random_state=0,设置初始化随机种子固定值为0
kmeans_result = model_kmeans.fit_predict(amount_shape) # 建立聚类
data['amount_kmeans'] = kmeans_result
data.head()
2.4针对连续数据的二值化
1、连续数据二值化是指将连续的变量特征进行二值的操作。
2、将每个数据点跟某个设定的阈值比较,大于阈值设置为某一固定值(例如1),小于阈值设置为某一固定值(例如0),最后得到一个只拥有两个值域的二值化数据集
3、需要注意的是二值化应用的前提:
- 数据集中所有的属性值所代表的含义相同或类似。如某图像数据集的颜色字段的数据集,其读取图像时的模式设置有灰度,RGB等,但都表示为颜色,此时该列特征含有相同,可对该列数据集进行二值化。
4、二值化方法:
→ sklearn.preprocessing的Binarizer方法
# 将income字段二值化,阈值设置为该列的均值
from sklearn import preprocessing
binarizer = preprocessing.Binarizer(threshold=data['income'].mean()) # 建立Binarizer模型对象
income = binarizer.fit_transform(data[['income']]) # 使用模型对象进行二值化
income.shape
income.resize(data['income'].shape) # 将列数据形状还原为(100,)
income.shape
data['income_binarizer'] = income
data.head()
如下图所示,是数据离散前后的对比:
三、优化离散
- 数据离散化的关键是,如何根据不同的数据特征和建模需求选择离散的方式。 → 离散化方式是否合理直接影响后续的数据建模和应用效果
- 如何优化离散? → 需要把自变量和目标变量联系起来考察。切分点是导致目标变量出现明显变化的折点。