用C的逻辑写MATLAB确实写的时候很直观,程序运行的过程看着也比较清楚,但是能用上MATLAB向量化的特性最好还是用MATLAB来干活。
MATLAB逻辑值索引
MATLAB逻辑值索引可以省掉大量的for循环,让程序看上去更简单,所以最好多用用。以一个最简单的任务为例,我们已经有了一个矩阵A,要建立一个新矩阵B,B保留A中第二个元素比0.5大的行:
>> A = rand(5)
A =
0.0357 0.7431 0.0318 0.6948 0.3816
0.8491 0.3922 0.2769 0.3171 0.7655
0.9340 0.6555 0.0462 0.9502 0.7952
0.6787 0.1712 0.0971 0.0344 0.1869
0.7577 0.7060 0.8235 0.4387 0.4898
在C当中,可能会利用一个for循环,对第二列中的所有元素进行判断,如果大于0.5,则将这一行加入一个新的矩阵中。但是在MATLAB里面,可以直接对这一整行进行判断:
>> A_logi = A(:,2) > 0.5
A_logi =
5×1 logical array
1
0
1
0
1
MATLAB里面,对于一整列的判断,会生成一个逻辑数组,可以看出,对一个5X1的数组进行判断,那么会出现一个5X1的逻辑数组,每一个对应的位置都是判断的结果。MATLAB里面,是可以直接使用逻辑数组对矩阵进行索引的。比如在这里,我们索引了A的A_logi行,那么MATLAB会抽出A中,A_logi对应为1的行。
>> B = A(A_logi,:)
B =
0.0357 0.7431 0.0318 0.6948 0.3816
0.9340 0.6555 0.0462 0.9502 0.7952
0.7577 0.7060 0.8235 0.4387 0.4898
这个任务就这样完成了。整个过程实际上写得紧凑一点就是:
B = A(A(:,2)>0.5,:);
如果说要直接去掉A中这些符合要求的行,那么可以直接让符合的元素为空:
>> A(A(:,2)>0.5,:) = []
A =
0.8491 0.3922 0.2769 0.3171 0.7655
0.6787 0.1712 0.0971 0.0344 0.1869
如果要剔除某些 NaN (not a number,即不可用数据)的数据,也可以用一样的方法处理,只是判断大小的函数要换成 isnan() 。如果说,要剔除所有含有 NaN 的行,而不论在哪一列,那么可以判断整个数组,然后用 any() 函数找出含有 NaN 的行。首先构造出一个用来测试的矩阵 A
>> A = rand(5)
A =
0.4456 0.6797 0.9597 0.2551 0.5472
0.6463 0.6551 0.3404 0.5060 0.1386
0.7094 0.1626 0.5853 0.6991 0.1493
0.7547 0.1190 0.2238 0.8909 0.2575
0.2760 0.4984 0.7513 0.9593 0.8407
>> A(randi(25,7,1)) = nan
A =
0.4456 0.6797 0.9597 0.2551 NaN
0.6463 NaN 0.3404 0.5060 0.1386
0.7094 0.1626 0.5853 0.6991 0.1493
0.7547 NaN 0.2238 0.8909 NaN
NaN 0.4984 0.7513 0.9593 0.8407
之后判断 A 里面哪些是 NaN
>> isnan(A)
ans =
5×5 logical array
0 0 0 0 1
0 1 0 0 0
0 0 0 0 0
0 1 0 0 1
1 0 0 0 0
再利用 any() 判断所有行是否至少含有一个 NaN ,any 是沿某一个维度判断的,调用方法为 any(A,dim) 这里因为是按行判断,也就是第二个维度,所以 dim 参数要写 2(默认为1)
>> any(isnan(A),2)
ans =
5×1 logical array
1
1
0
1
1
然后再用刚才的方法取 A 中的行就可以了。