在分箱前,一定要先排序数据,再将它们分到等深(等宽)的箱中。
常见的有两种分箱方法:等深分箱和等宽分箱。
等深分箱:按记录数进行分箱,每箱具有相同的记录数,每箱的记录数称为箱的权重,也称箱子的深度。
等宽分箱:在整个属性值的区间上平均分布,即每个箱的区间范围设定为一个常量,称为箱子的宽度。
将数据划分到不同的箱子之后,可以运用如下三种策略对每个箱子中的数据进行平滑处理:
平均值平滑:箱中的每一个值被箱中数值的平均值替换。
中值平滑:箱中的每一个值被箱中数值的中值替换。
边界平滑:箱中的最大值和最小值称为箱子的边界,箱中的每一个值被最近的边界值替换。
首先用rand()函数随机生成20*5的矩阵,其数据范围为[0,1]。
- clear;clc; % 清除变量和命令窗口
-
- A=rand(20,5); % 随机生成20*5的矩阵,其中每个数取值范围[0,1]
- fprintf("当前生成的原数据:\n");
- disp(A);
-
- % 排序,参数1表示按列排序,取2为按行排序;'ascend'为升序,'descend'为降序
- A=sort(A,1,'ascend');
- fprintf("将原数据的每列排序后:\n");
- disp(A);
-
- h=input("请输入等深分箱的深度h(1
); -
- % 检查输入变量h是否有效
- if ~isnumeric(h) || ~isscalar(h) || h<=1 || h>=20 || h~=floor(h)
- error("输入变量h必须是一个大于1小于20的正整数");
- end
-
- %% 对每列进行等深分箱,然后求每个箱子的均值
- [n,m]=size(A); % n行m列
- B=zeros(n,m); % 预分配输出变量B
- for j=1:m % 列j
- for i=1:h:n % 行i
- % 当前箱子第一个数位置为i,最后一个数位置为min(i+h-1,n)
- p1=int64(i); % 转换成整数(i默认是double类型,但是索引必须要为整数)
- p2=int64(min(i+h-1,n));
- B(p1:p2,j)=mean(A(p1:p2,j)); % 当前箱子的均值
- end
- end % 结束行循环
-
- fprintf("\n经过等深分箱,用箱均值平滑处理后的数据:\n");
- disp(B);
for i=1:h:n 的含义是:
- i 是一个循环变量,它的初始值是 1。
- h 是一个输入变量,它表示等深分箱的深度。
- n 是一个由 size 函数得到的变量,它表示矩阵 A 的行数。
- 这个循环的作用是从第一行开始,每隔 h 行取一行作为一个箱子的起始位置,然后计算这个箱子中所有元素的均值,并赋给输出矩阵 B 的相应位置。
isnumeric 函数是一个用于判断输入是否为数值数组的函数。数值数组是指由数值类型的元素组成的数组,例如整数、浮点数、无穷大或非数字。MATLAB 中的数值类型包括 int8, int16, int32, int64, uint8, uint16, uint32, uint64, single, 和 double。
isnumeric 函数的语法格式是:
TF = isnumeric(A)其中,A 是输入数组,可以是任意维度的;TF 是输出逻辑值,如果 A 是数值数组,则返回 1 (true),否则返回 0 (false)。
例如,如果 A 是一个包含整数和浮点数的矩阵,那么 isnumeric(A) 将返回 1;如果 A 是一个包含字符串或单元数组的矩阵,那么 isnumeric(A) 将返回 0。
~isscalar(h) 函数是一个逻辑表达式,它用于判断 h 是否不是一个标量。标量是一个大小为 1×1 的二维数组,也就是一个单个的数值。如果 h 不是一个标量,那么 ~isscalar(h) 将返回 1 (true),否则返回 0 (false)。
python代码为
- import numpy as np # 导入 numpy 库
- =
-
- A = np.random.rand(20,5) # 随机生成 20*5 的矩阵,其中每个数取值范围 [0,1]
- print("当前生成的原数据:")
- print(A)
-
- # 排序,参数 0 表示按列排序,取 1 为按行排序;'ascend' 为升序,'descend' 为降序
- A = np.sort(A, axis=0, kind='quicksort') # 使用快速排序算法
- print("将原数据的每列排序后:")
- print(A)
-
- h = int(input("请输入等深分箱的深度 h (1
)) # 输入一个整数 -
- # 检查输入变量 h 是否有效
- if not isinstance(h, int) or h <= 1 or h >= 20: # 如果 h 不是一个大于 1 小于 20 的整数
- raise ValueError("输入变量 h 必须是一个大于 1 小于 20 的正整数") # 抛出异常
-
- # 对每列进行等深分箱,然后求每个箱子的均值
- n, m = A.shape # n 行 m 列
- B = np.zeros((n,m)) # 预分配输出变量 B
- for j in range(m): # 列 j
- for i in range(0, n, h): # 行 i
- # 当前箱子第一个数位置为 i,最后一个数位置为 min(i+h,n)
- p1 = int(i) # 转换成整数 (i 默认是 double 类型,但是索引必须要为整数)
- p2 = int(min(i+h,n))
- B[p1:p2,j] = np.mean(A[p1:p2,j]) # 当前箱子的均值
-
- print("\n经过等深分箱,用箱均值平滑处理后的数据:")
- print(B)
输入的深度为3:
- 当前生成的原数据:
- A =
-
- 0.4067 0.4504 0.5747 0.5154 0.9969
- 0.6669 0.2057 0.3260 0.6575 0.5535
- 0.9337 0.8997 0.4564 0.9509 0.5155
- 0.8110 0.7626 0.7138 0.7223 0.3307
- 0.4845 0.8825 0.8844 0.4001 0.4300
- 0.7567 0.2850 0.7209 0.8319 0.4918
- 0.4170 0.6732 0.0186 0.1343 0.0710
- 0.9718 0.6643 0.6748 0.0605 0.8877
- 0.9880 0.1228 0.4385 0.0842 0.0646
- 0.8641 0.4073 0.4378 0.1639 0.4362
- 0.3889 0.2753 0.1170 0.3242 0.8266
- 0.4547 0.7167 0.8147 0.3017 0.3945
- 0.2467 0.2834 0.3249 0.0117 0.6135
- 0.7844 0.8962 0.2462 0.5399 0.8186
- 0.8828 0.8266 0.3427 0.0954 0.8862
- 0.9137 0.3900 0.3757 0.1465 0.9311
- 0.5583 0.4979 0.5466 0.6311 0.1908
- 0.5989 0.6948 0.5619 0.8593 0.2586
- 0.1489 0.8344 0.3958 0.9742 0.8979
- 0.8997 0.6096 0.3981 0.5708 0.5934
-
- 将原数据的每列排序后:
- A =
-
- 0.1489 0.1228 0.0186 0.0117 0.0646
- 0.2467 0.2057 0.1170 0.0605 0.0710
- 0.3889 0.2753 0.2462 0.0842 0.1908
- 0.4067 0.2834 0.3249 0.0954 0.2586
- 0.4170 0.2850 0.3260 0.1343 0.3307
- 0.4547 0.3900 0.3427 0.1465 0.3945
- 0.4845 0.4073 0.3757 0.1639 0.4300
- 0.5583 0.4504 0.3958 0.3017 0.4362
- 0.5989 0.4979 0.3981 0.3242 0.4918
- 0.6669 0.6096 0.4378 0.4001 0.5155
- 0.7567 0.6643 0.4385 0.5154 0.5535
- 0.7844 0.6732 0.4564 0.5399 0.5934
- 0.8110 0.6948 0.5466 0.5708 0.6135
- 0.8641 0.7167 0.5619 0.6311 0.8186
- 0.8828 0.7626 0.5747 0.6575 0.8266
- 0.8997 0.8266 0.6748 0.7223 0.8862
- 0.9137 0.8344 0.7138 0.8319 0.8877
- 0.9337 0.8825 0.7209 0.8593 0.8979
- 0.9718 0.8962 0.8147 0.9509 0.9311
- 0.9880 0.8997 0.8844 0.9742 0.9969
-
- 请输入等深分箱的深度h(1
20):3 -
- 经过等深分箱,用箱均值平滑处理后的数据:
- B =
-
- 0.2615 0.2013 0.1273 0.0521 0.1088
- 0.2615 0.2013 0.1273 0.0521 0.1088
- 0.2615 0.2013 0.1273 0.0521 0.1088
- 0.4262 0.3195 0.3312 0.1254 0.3279
- 0.4262 0.3195 0.3312 0.1254 0.3279
- 0.4262 0.3195 0.3312 0.1254 0.3279
- 0.5472 0.4519 0.3899 0.2633 0.4527
- 0.5472 0.4519 0.3899 0.2633 0.4527
- 0.5472 0.4519 0.3899 0.2633 0.4527
- 0.7360 0.6490 0.4443 0.4851 0.5541
- 0.7360 0.6490 0.4443 0.4851 0.5541
- 0.7360 0.6490 0.4443 0.4851 0.5541
- 0.8526 0.7247 0.5611 0.6198 0.7529
- 0.8526 0.7247 0.5611 0.6198 0.7529
- 0.8526 0.7247 0.5611 0.6198 0.7529
- 0.9157 0.8478 0.7031 0.8045 0.8906
- 0.9157 0.8478 0.7031 0.8045 0.8906
- 0.9157 0.8478 0.7031 0.8045 0.8906
- 0.9799 0.8979 0.8495 0.9626 0.9640
- 0.9799 0.8979 0.8495 0.9626 0.9640
输入箱子的宽度w(0 if A(i,j)-A(pos,j)>w 这段代码的作用是判断当前元素是否属于当前箱子。如果当前元素与当前箱子的第一个元素的差大于 w,那么说明当前元素已经超出了当前箱子的范围,需要开始新的一个箱子;如果不大于 w,那么说明当前元素还在当前箱子内,继续循环。 输入的宽度为0.2:
代码运行结果