Removing rows from matrix - arrays

I have a question above removing rows from a matrix. I have the code below which removes the rows I want, but the problem is each time a row is removed it changes the size of the matrix. When the size of the matrix changes, the for loops can no longer run through the original size of the matrix because it has changed. Does anyone know how to get around this? Thanks.
for i = 1:NT
for j = 1:NP
for k = 1:NP
if ContactPartData((i-1)*(NP*(NP-1)) + ((j-1)*NP + k),2) == 0
ContactPartData((i-1)*(NP*(NP-1)) + ((j-1)*NP + k),:) = [];
else
end
end
end
end

For these cases, it is typically easier to record which rows you want to remove, and then remove them all at once at the end. This is more efficient than repeatedly removing a single row. And it solves your problem at the same time!
toremove = false(size(ContactPartData,1),1);
for i = 1:NT
for j = 1:NP
for k = 1:NP
if ContactPartData((i-1)*(NP*(NP-1)) + ((j-1)*NP + k),2) == 0
toremove((i-1)*(NP*(NP-1)) + ((j-1)*NP + k)) = true;
end
end
end
end
ContactPartData(toremove,:) = [];
Of course, in this particular case, the loop is not needed at all:
toremove = ContactPartData(:,2) == 0;
ContactPartData(toremove,:) = [];
Additionally, it might be more efficient to do it the other way around, selecting which rows to preserve (time the code to find out!):
tokeep = ContactPartData(:,2) ~= 0;
ContactPartData = ContactPartData(tokeep,:);

Related

Index Subset of Array in For Loop in MATLAB

I have a question regarding indexing and loops in MATLAB. I have a vector of length n (named data in the code below). I want to examine this vector 4 elements at a time inside of a for loop. How can I do this? My attempt included below does not work because it will exceed the array dimensions at the end of the loop.
for k = 1:length(data)
index = k:k+3;
cur_data = data(index);
pre_q_data1 = cur_data(1);
pre_q_data2 = cur_data(2);
% Interweaving the data
q = [pre_q_data1; pre_q_data2];
qdata = q(:)';
pre_i_data1 = cur_data(3);
pre_i_data2 = cur_data(4);
i = [pre_i_data1; pre_i_data2];
idata = i(:)';
end
You shouldn't have k go all the way to length(data) if you're planning on indexing up to k+3.
I've also taken the liberty of greatly simplifying your code, but feel free to ignore that!
for k = 1:length(data)-3
% maximum k = length(data)-3, so maximum index = length(data)-3+3=length(data)
index = k:k+3;
cur_data = data(k:k+3);
% Interweaving the data
q = cur_data(1:2); % transpose at end of line here if need be
i = cur_data(3:4); % could just use data(k+2:k+3) and not use cur_data
end

A simple sorting algorithm

This is a simple sorting function that I wrote in Matlab:
function [matrix] = sorting(matrix)
for index = 1:length(matrix)-1
if matrix(index) > matrix(index + 1)
temp = matrix(index + 1);
matrix(index + 1) = matrix(index);
matrix(index) = temp;
end
end
check_sorted(matrix)
end
function [matrix] = check_sorted(matrix)
count = 0;
for index = 1:length(matrix)-1
if matrix(index) < matrix(index + 1)
count = count + 1;
end
end
if count+1 < length(matrix)
sorting(matrix);
end
end
The input for sorting function is a 1D array, e.g. [4 3 2 1], and it successfully returns the sorted array [1 2 3 4] for the first time I call it, but then it starts to return unsorted arrays?
You've got a missing semicolon that is causing the results of each call to check_sorted to be displayed, which is confusing things. If you add the semicolon, the output from sorting with the array [2 4 1 3] suggested in the comments is:
>> sorting([2 4 1 3])
ans =
2 1 3 4
Clearly this isn't sorted. The problem is that MATLAB passes function arguments by value, not by reference. Since you're not returning the re-sorted matrix from check_sorted or updating the return matrix in sorting the original matrix never gets updated. You need to change at least one line in each function (changed lines are commented):
function [matrix] = check_sorted(matrix)
count = 0;
for index = 1:length(matrix)-1
if matrix(index) < matrix(index + 1)
count = count + 1;
end
end
if count+1 < length(matrix)
matrix = sorting(matrix); % change: return re-sorted matrix
end
end
function [matrix] = sorting(matrix)
for index = 1:length(matrix)-1
if matrix(index) > matrix(index + 1)
temp = matrix(index + 1);
matrix(index + 1) = matrix(index);
matrix(index) = temp;
end
end
matrix = check_sorted(matrix); % change: return checked matrix
end
Now the matrix will be updated if it is not sorted on the first (or any subsequent) pass and the fully sorted matrix will be returned by sorting.
This is an odd sort of recursion that really isn't necessary. If you change check_sorted to return a boolean value, true for sorted, false for not sorted, you can change that recursion to a while loop around the for loop in sorting:
function [TF] = check_sorted2(matrix)
count = 0;
for index = 1:length(matrix)-1
if matrix(index) < matrix(index + 1)
count = count + 1;
end
end
TF = count+1 == length(matrix); % TF = true if matrix is sorted
% TF = false otherwise
end
function [matrix] = sorting2(matrix)
while ~check_sorted2(matrix) % keep going until matrix is sorted
for index = 1:length(matrix)-1
if matrix(index) > matrix(index + 1)
temp = matrix(index + 1);
matrix(index + 1) = matrix(index);
matrix(index) = temp;
end
end
end
end
Of course the whole thing can be optimized and vectorized, but this will at least get you going.
i tested your algorithms and it worked. so something else might be wrong. but this algorithm is very very inefficient. you may google sort and pick one that suits you.
if you really want to stick with the algorithm, you could improve it by shortening the two loops. for example, after first call to sorting, for each subsequent call to sorting, you could shorten the loop cycle by 1 because the first call to sorting would put the largest number to the end of the array, the second call would put the second largest to the second from the end, and so on. this is so called bubble sorting. also in check_sorted, you don't need to go through the entire length of the array to check if the array has been sorted. as soon as you see matrix(index) > matrix(index + 1), you can immediately exit the loop (after you set a flag to indicate the array hasn't been sorted).

Array not defined

I'm still confused why am not able to know the results of this small algorithm of my array. the array has almost 1000 number 1-D. am trying to find the peak and the index of each peak. I did found the peaks, but I can't find the index of them. Could you please help me out. I want to plot all my values regardless the indexes.
%clear all
%close all
%clc
%// not generally appreciated
%-----------------------------------
%message1.txt.
%-----------------------------------
% t=linspace(0,tmax,length(x)); %get all numbers
% t1_n=0:0.05:tmax;
x=load('ww.txt');
tmax= length(x) ;
tt= 0:tmax -1;
x4 = x(1:5:end);
t1_n = 1:5:tt;
x1_n_ref=0;
k=0;
for i=1:length(x4)
if x4(i)>170
if x1_n_ref-x4(i)<0
x1_n_ref=x4(i);
alpha=1;
elseif alpha==1 && x1_n_ref-x4(i)>0
k=k+1;
peak(k)=x1_n_ref; // This is my peak value. but I also want to know the index of it. which will represent the time.
%peak_time(k) = t1_n(i); // this is my issue.
alpha=2;
end
else
x1_n_ref=0;
end
end
%----------------------
figure(1)
% plot(t,x,'k','linewidth',2)
hold on
% subplot(2,1,1)
grid
plot( x4,'b'); % ,tt,x,'k'
legend('down-sampling by 5');
Here is you error:
tmax= length(x) ;
tt= 0:tmax -1;
x4 = x(1:5:end);
t1_n = 1:5:tt; % <---
tt is an array containing numbers 0 through tmax-1. Defining t1_n as t1_n = 1:5:tt will not create an array, but an empty matrix. Why? Expression t1_n = 1:5:tt will use only the first value of array tt, hence reduce to t1_n = 1:5:tt = 1:5:0 = <empty matrix>. Naturally, when you later on try to access t1_n as if it were an array (peak_time(k) = t1_n(i)), you'll get an error.
You probably want to exchange t1_n = 1:5:tt with
t1_n = 1:5:tmax;
You need to index the tt array correctly.
you can use
t1_n = tt(1:5:end); % note that this will give a zero based index, rather than a 1 based index, due to t1_n starting at 0. you can use t1_n = 1:tmax if you want 1 based (matlab style)
you can also cut down the code a little, there are some variables that dont seem to be used, or may not be necessary -- including the t1_n variable:
x=load('ww.txt');
tmax= length(x);
x4 = x(1:5:end);
xmin = 170
% now change the code
maxnopeaks = round(tmax/2);
peaks(maxnopeaks)=0; % preallocate the peaks for speed
index(maxnopeaks)=0; % preallocate index for speed
i = 0;
for n = 2 : tmax-1
if x(n) > xmin
if x(n) >= x(n-1) & x(n) >= x(n+1)
i = i+1;
peaks(i) = t(n);
index(i) = n;
end
end
end
% now trim the excess values (if any)
peaks = peaks(1:i);
index = index(1:i);

How can I vectorize this code?

First of all I should say that I couldn't find the appropriate title for my question so I would appreciate anyone who will edit the title!
Suppose that I have a 18432x1472 matrix and I want to convert it to a 3072x1472 one ( 18432/6 = 3072 ) in this form:
the mean of elements (1,6),(2,6),...,(6,6) of the old matrix will go to the element (1,1) of the new one
the mean of elements (7,6),(8,6),...,(12,6) of the old matrix will go to the element (2,1) of the new one and so on
Up to now I have written this code:
function Out = MultiLooking( In )
MatrixIn = double(In);
m = size(In,1);
InTranspose = MatrixIn';
A = zeros(m,m/6);
for i = 1:(m/6)
A(6*(i-1)+1,i) = 1;
A(6*(i-1)+2,i) = 1;
A(6*(i-1)+3,i) = 1;
A(6*(i-1)+4,i) = 1;
A(6*(i-1)+5,i) = 1;
A(6*(i-1)+6,i) = 1;
end
X = (InTranspose*A)/6;
Out1 = X';
Out = uint8(Out1);
end
But it is alittle slow and for my polarimetric SAR data, computer gets hanged out for a while when running this code so I need the code to run faster!
Can anyone suggest me a faster code for doing this purpose???
An alternative to Divakar's nice answer: use blockproc (Image Processing Toolbox):
blockproc(MatrixIn, [6 size(MatrixIn,2)], #(x) mean(x.data))
Try this -
%// Assuming MatrixIn is your input matrix
reshape(mean(reshape(MatrixIn,6,[])),size(MatrixIn,1)/6,[])
Alternative Solution using cell arrays (performance improvement over previous code is doubtful though) -
c1 = cellfun(#mean,mat2cell(MatrixIn,6.*ones(1,size(MatrixIn,1)/6),size(MatrixIn,2)),'uni',0)
out = vertcat(c1{:})

Replacing repeated values of cell with empty [] - MATLAB

So I have a 1x348 cell composed of numbers and empty brackets. Ie ... [] [] [] [169] [170] [170] [170] [171] [172] [] []...
All what I want to do is change the repeated numbers to empty brackets []. I need to hold the places. I tried this, but am not having any success. It is also not ideal, because in the case with more than one repeat, it would just replace every other repeat with [].
for jj = 1:length(testcell);
if testcell{jj} == testcell{jj-1}
testcell{jj} = []
end
Any help would be greatly appreciated :-)
Lets assume you have {1,1,1}. First iteration will change this to {1,[],1} and second iteration does not see any repetition. Thus iterating backwards is probably the easiest solution:
for jj = length(testcell):-1:2
if testcell{jj} == testcell{jj-1}
testcell{jj} = [];
end
end
Then the first step will result in {1,1,[]} and the second in {1,[],[]}
The only thing your code lacks is some variable to store current value:
current = testcell{1};
for jj = 2:length(testcell)
if testcell{jj} == current
testcell{jj} = [];
else
current = testcell{jj};
end
end
But it's better to use Daniel's solution =).
Alternatively, you could use NaN values to represent cells with empty matrices, and vectorize your code:
testcell(cellfun('isempty', testcell)) = {NaN};
[U, iu] = unique([testcell{end:-1:1}]);
testcell(setdiff(1:numel(testcell), numel(testcell) - iu + 1)) = {NaN};
testcell(cellfun(#isnan, testcell)) = {[]};

Resources