目录
参考资料:《Python数据分析与数据化运营》宋天龙
数据离散化的应用场景和必要性
数据离散化大多是针对连续数据进行的,处理之后的数据将从连续属性变为离散属性。离散化处理的必要性:
- 节约计算资源,提高计算效率。
- 算法模型(尤其是分类模型)的计算需要。虽然很多模型,例如决策树可以支持输入连续型数据,但是决策树本身会先将连续型数据转化为离散型数据,因此离散化转换是一个必要步骤。
- 增强模型的稳定性和准确度。数据离散化之后,处于异常状态的数据不会明显的突出异常特征,而是会被划分为一个子集中的一部分,因此异常数据对模型的影响会大大降低,尤其是基于距离计算的模型(例如K均值、协同过滤等)效果明显。
- 特定数据处理和分析的必要步骤,尤其在图像处理方面应用广泛。大多数图像做特征检测(以及其他基于特征的分析)时,都需要先将图像做二值化处理,二值化也是离散化的一种。
- 模型结果应用和部署的需要。如果原始数据的值域分布过多,或值域划分不符合业务逻辑,那么模型结果将很难被业务理解并应用。
说明:离散化通常针对连续数据进行处理,但是在很多情况下也可以针对已经是离散化的数据进行处理。这种场景一般是离散数据本身的划分过于复杂、琐碎甚至不符合业务逻辑,需要进一步做数据聚合或重新划分。
针对时间数据的离散化
针对时间数据的离散化主要用于以时间为主要特征的数据集中和粒度转换,离散化处理后将分散的时间特征转换为更高层次的时间特征。
常见的针对时间数据的离散化操作分为以下两类:
- 针对一天中的时间离散化。一般是将时间戳转换为秒、分钟、小时或上下午。
- 针对日粒度以上数据的离散化。一般是将日期转化为周数、周几、月、工作日或休息日、季度、年等。
针对多值离散数据的离散化
针对多值离散数据的离散化指的是要进行离散化处理的数据是分类或顺序数据。有可能是因为之前划分的逻辑有问题,需要重新划分,这种问题通常都是由于业务逻辑的变更。
针对连续数据的离散化
针对连续数据的离散化是主要的离散化应用,在分类或关联分析中应用尤其广泛,这些算法的结果以类别标识为基础。
常见实现连续数据离散化的方法包括:
- 分位数法:使用四分位、五分位等分位数进行离散化处理,这种方法简单易行。
- 距离区间法:可使用等距区间或自定义区间的方式进行离散化,这种操作更加灵活且能满足自定义需求,另外该方法(尤其是等距区间)可以较好的保持数据原有的分布。
- 频率区间法:将数据按照不同数据的频率分布进行排序,然后按照等频率或指定频率离散化,这种方法会把数据变换成均匀分布,好处是各区间的观察值是相同的,不足是已经改变了原有数据的分布状态。
- 聚类法:例如使用K均值将样本集分为多个离散化的簇。
- 卡方:通过使用基于卡方的离散化方法,找出数据的最佳临近区间并合并,形成较大的区间。
针对连续数据的二值化
在很多场景下,我们可能需要将变量特征进行二值化操作:每个数据点跟阀值比较,大于阀值设置为固定值(例如1),小于阀值设置为固定值(例如0),然后得到一个二值化数据集。
说明:二值化后的值的设置取决于场景,例如大部分数据的处理可以设置为1或0;在图像处理中则会设置为0或255。
代码如下:
# 导入库
import pandas as pd
from sklearn.cluster import KMeans
from sklearn import preprocessing
# 读取数据
df = pd.read_table('data.txt', names=['id', 'amount', 'income', 'datetime','age'])
print(df.head(5))
# 一、针对时间数据的离散化
for i, single_data in enumerate(df['datetime']):
single_data = pd.to_datetime(single_data) # 将时间字符串格式转换为datetime格式
df['datetime'][i] = single_data.weekday() # 离散化为周几
print(df.head(5))
# 二、针对多值离散数据的离散化
map_df = pd.DataFrame(
[['0-10', '0-40'], ['10-20', '0-40'], ['20-30', '0-40'], ['30-40', '0-40'],
['40-50', '40-80'],
['50-60', '40-80'], ['60-70', '40-80'], ['70-80', '40-80'],
['80-90', '>80'], ['>90', '>80']],
columns=['age', 'age2']) # 定义一个要转换的新区间
df_tmp = df.merge(map_df, how='inner')
df = df_tmp.drop('age', axis=1)
df=df.rename(columns={'age2':'age'})
print(df.head(5))
# 三、针对连续数据的离散化
# 方法1:自定义分箱区间实现离散化
bins = [0, 200, 1000, 5000, 10000] # 自定义区间边界
df['amount1'] = pd.cut(df['amount'], bins) # 使用边界做离散化
print(df.head(5))
# 方法2:使用4分位数实现离散化
df['amount2'] = pd.qcut(df['amount'], 4, labels=['bad', 'medium', 'good','awesome']) # 按四分位数进行分隔
print(df.head(5))
# 方法3 使用聚类法实现离散化
kmeans_model = KMeans(n_clusters=4, random_state=0) # 创建KMeans模型并指定要聚类数量
kmeans_result = kmeans_model.fit_predict(df[['amount']]) # 建模聚类
df['amount3'] = kmeans_result # 新离散化的数据合并到原数据框
df = df.drop('amount', axis=1)
print(df.head(5))
# 四、针对连续数据的二值化
binarizer_scaler = preprocessing.Binarizer(threshold=df['income'].mean()) # 建立Binarizer模型对象
income_tmp = binarizer_scaler.fit_transform(df[['income']]) # Binarizer标准化转换
df['income'] = income_tmp
print(df.head(5))
上述过程中,主要需要考虑的关键点是:如何根据不同的数据特点和建模需求选择最合适的离散化方式,因为离散化方式的是否合理会直接影响后续数据建模和应用效果。还需要说明的是,有些模型对于离散化有更多的要求:
- 使用决策树时往往倾向于少量的离散化区间,原因是过多的离散化将使得规则过多受到碎片区间的影响。
- 关联规则需要对所有特征一起离散化,原因是关联规则关注的是所有特征的关联关系,如果对每个列单独离散化将失去整体规则性。