Delete row if element is out of specified range

14 次查看(过去 30 天)
I have the following:
min = 67;
max = 69;
nmat =
0 0.9000 1.0000 64.0000 82.0000 0 0.5510
1.0000 0.9000 1.0000 71.0000 89.0000 0.6122 0.5510
2.0000 0.4500 1.0000 71.0000 82.0000 1.2245 0.2755
2.5000 0.4500 1.0000 69.0000 70.0000 1.5306 0.2755
3.0000 0.4528 1.0000 67.0000 72.0000 1.8367 0.2772
3.5000 0.4528 1.0000 66.0000 72.0000 2.1429 0.2772
4.0000 0.9000 1.0000 64.0000 70.0000 2.4490 0.5510
5.0000 0.9000 1.0000 66.0000 79.0000 3.0612 0.5510
6.0000 0.9000 1.0000 67.0000 85.0000 3.6735 0.5510
7.0000 1.7500 1.0000 66.0000 72.0000 4.2857 1.0714
9.0000 0.4528 1.0000 64.0000 74.0000 5.5102 0.2772
9.5000 0.4528 1.0000 67.0000 81.0000 5.8163 0.2772
10.0000 0.9000 1.0000 71.0000 83.0000 6.1224 0.5510
11.0000 0.4528 1.0000 71.0000 78.0000 6.7347 0.2772
11.5000 0.4528 1.0000 69.0000 73.0000 7.0408 0.2772
12.0000 0.4528 1.0000 67.0000 71.0000 7.3469 0.2772
12.5000 0.4528 1.0000 66.0000 69.0000 7.6531 0.2772
13.0000 0.4528 1.0000 67.0000 83.0000 7.9592 0.2772
13.5000 0.4528 1.0000 66.0000 72.0000 8.2653 0.2772
14.0000 0.4528 1.0000 64.0000 74.0000 8.5714 0.2772
14.5000 0.4528 1.0000 63.0000 70.0000 8.8776 0.2772
15.0000 0.9000 1.0000 64.0000 82.0000 9.1837 0.5510
16.0000 1.8028 1.0000 64.0000 75.0000 9.7959 1.1037
and I would like to delete any row in which the value for (i,4) is out of the particular range:
min < nmat(i,4) < max
I am aware that Matlab does not like the syntax a < b < c, but I have tried several variations of code and cannot understand where my error is.
min = 67;
max = 69;
for i=1:length(nmat)
if (nmat(i,4) < min) || (nmat(i,4) > max)
nmat(i, :) = [];
end
end
Logical operations aside, I cannot even get the loop to properly perform the more simple task of deleting rows with an (i,4) value below the min:
min = 67;
max = 69;
for i=1:length(nmat)
if nmat(i,4) < min
nmat(i, :) = [];
end
end
Any help is much appreciated.

回答(3 个)

Jan
Jan 2015-12-18
编辑:Jan 2015-12-20
toDelete = ((min < nmat(:,4)) | (nmat(:,4) < max));
nmat(toDelete, :) = [];
Your loop must fail, because it checks all rows of teh matrix, but this matrix shrinks during the processing. The limits of the loop are determined once only at the beginning.
Alternatively you could run the loop from size(nmat, 1) backward to 1. But the iterative changing of the array size wastes resources, so better avoid this.
  1 个评论
JZ
JZ 2015-12-18
Jan, why am I getting the following error with your code?
Subscript indices must either be real positive integers or logicals.

请先登录,再进行评论。


Guillaume
Guillaume 2015-12-18
First a comment on your code:
for i = 1:length(nmat)
In my opinion, length should be removed from matlab. There are clearer alternatives and most people who use it don't understand how it works.
With a 2d matrix, length is the size of the largest dimension. So if the matrix has more rows than columns, it's the number of rows and if the matrix has more columns than rows, it's the number of columns.
In your particular case, length might start as the number of columns, but once you've deleted enough will switch the number of columns!
It's better to always be explicit. If you want the number of elements in a vector use numel, if you want the number of rows in a matrix use size(m, 1), and size(m, 2) to get the number of columns.
Second comment: Do not use min and max as variable names as you won't be able to use the min and max function of matlab.
Now, to answer your question, the simplest way to delete your rows is with:
thresholdmin = 67;
thresholdmax = 69;
nmat(nmat(:, 4) < thresholdmin | nmat(:, 4) > thresholdmax, :) = []
  3 个评论
Guillaume
Guillaume 2015-12-18
First, your expression does not work for two reasons, a) you've got the wrong column (2 instead of 1) and b) you've fallen foul of operator precedence. In matlab AND always takes precedence over OR, so your expression says:
(less than 70 in column 4 AND less than 1 in column 2) OR (greater than 3 in column 2)
The answer is to use parentheses just as you'd written in your statement, so:
nmat(nmat(:, 2) < col4min & (nmat(:, 1) < col2min | nmat(:, 1) > col2max), :) = []
The way this works, nmat(:, x) is a column vector with as many rows as nmat. Compared to a scalar you get a column vector of logicals. This is then combined with other column vectors of logicals with & or |, so in the end you have a column vector to select with row you want to pick / discard. To delete a whole row, you need to select all the columns, hence why you have : for the columns. In short, you're simply using
nmat(rowidx, colidx) = []
where rowidx is a logical vector to select which rows you want, and colidx is : to select all columns.
JZ
JZ 2015-12-18
Thanks for all the explanations - It seems I have it working now.

请先登录,再进行评论。


Stalin Samuel
Stalin Samuel 2015-12-18
min = 67;
max = 69;
nmat = randi([1 500],100,100);%for example
[row,col] = find(nmat>min&nmat<max)
nmat(unique(row),:)=[]

类别

Help CenterFile Exchange 中查找有关 Programming 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by