Comparing individual matrix elements in MATLAB? - arrays

I need to compare a value in a multidimentional array and according to this comparison, I need to assign a value of another matrix in the same index to a new matrix of the same size in the same index. Can you give me an idea on how to do this?
Here's the code below using the for loop, but I need to do this without using a for loop.
for i = 1:sizeOfMatrix(1, 1)
for j = 1:sizeOfMatrix(1, 2)
if grayImage(i, j) > t
result(i, j) = 0;
else
result(i, j) = grayImage(i, j);
end
end
end
where t is the value that I need to compare with.

Use logical indexing:
result = zeros(size(grayImage));
result(grayImage <= t) = grayImage(grayImage <= t);
This is a much faster and cleaner way to access matrix elements conditionally.
Alternatively, you can do:
result = grayImage;
result(grayImage > t) = 0;

Related

How to create matrix in matlab that adds cells horizontally

I want to create a matrix, for example, a 1xn, where n is determined by another input.
For example, I have the following:
Example = [3 5 7 9];
New_matrix = [int_col(Example (1)) int_col(Example (2)) int_col(Example (3)) int_col(Example (4))];
This New_matrix is how I want my outputs.
However, for my actual data input, my Example matrix is 1x47. How can I put this in a for loop so it gives the outputs of 1 to a specified number for all of the length Example? (keeping it horizontal as well)
Help function I used is added here:
% Helper function added as well
function v = int_col(n)
v = zeros(1,n);
for index=1:n
val = randi(n);
while (val == index || any(val == v))
val = randi(n);
if (index == n && (any(v == n) ~= 1))
val = n;
break
end
end
v(index) = val;
if (index == n && val == n)
% v(n) = v(n-1);
% v(n-1) = n;
end
if n == 1
v = 1;
end
end
v = v';
v = (sortrows(v))';
end
Are you trying to reimplement randperm() in int_col()? I'm not sure what the purpose of running sortrows() on each column separately is, but I guess this may be what you wanted:
% Make up vector of column lengths
Example=randi(60,[1 47]);
% Create matrix
New_matrix=nan([max(Example) numel(Example)]);
for i=1:numel(Example)
New_matrix(1:Example(i),i)=randperm(Example(i));
end
% Sort matrix rows from left to right
New_matrix=sortrows(New_matrix);
Please note that all columns in a matrix must have the same number of entries, so you will need to pad shorter columns with some value; a typical choice is NaN, which is treated as a special value by sortrows() and some other functions.
~
If my guess is incorrect and you do mean your code as it currently is, you just need:
New_matrix=[];
for i=1:numel(Example)
New_matrix=[New_matrix 1:Example(i)];
end
Changing the size of New_matrix on every iteration is generally not good practice, but for 47 iterations only this should be fine.

Array's length in Matlab

How I could determine the number of elements from an array in Matlab, without using functions such as length(), size(), etc. ?
Thanks you !
The logic is to iterate over the cells until an empty cell is encountered. I have taken two variables for iteration namely, i and j. i is for rows and j is for columns.
Initially set the value of i and j as i=1 and j=1. Now in a while loop iterate by incrementing j and keeping i = 1 as constant.
** First try to copy that cell in a variable x. If that cell is an empty cell an error will pop up. Aim is to take advantage of this error using try/catch statements.
Scince the statement x = vec(i,j); is written in the try block so on encountering an empty cell instead of try the catch block will be executed where flag = 0 makes the flag 0, this will cause the while loop to end.
So, we have the number of columns stored in j and the while loop terminates on encountering an empty cell.
flag = 1;
i = 1;
j = 1;
while(flag==1) % loop will continue till flag is 1 (or say flag is HIGH)
try
x = vec(i,j); % Try to copy this cell of array vec in x
j = j+1; % if successful to copy then increment value of j else catch block is executed
catch
flag = 0; % Set flag = 0 (or low) to end the while loop
end
end
j = j - 1; % The value of j comes out to be one greater than number of columns hence decrementing by 1
%
% WE HAVE THE NUMBER OF COLUMNS !!
%
% WE WILL PERFORM SAME THING TO GET THE NUMBER OF ROWS BY INCREMENTING i AND
% KEEPING j AS CONSTANT
flag=1;
while(flag==1)
try
x = vec(i,j);
i = i+1;
catch
flag = 0;
end
end
i = i - 1;
% i is the number of rows in the matrix or array
% j is the number of columns in the matrix
dim = [i,j] % vector named dim(or say matrix named dim) contains the required output
dim contains the size of vec

Matlab variable size arrays

I am very new to Matlab, and I feel completely overwhelmed by the use of arrays. What is the most efficient implementation of the following C++ code in Matlab?
A = std::vector<double>();
for (int i = 0; i < 100; i++) {
if (complicatedBoolFunction(i)) {
A.push_back(i);
}
}
Edit: By efficiency I mean to use as little resources as possible to grow the array A - that is, to avoid copy-pasting it into temporary memory
You can do this 2 ways
Pre-allocating for the maximum size, and removing unused elements. This has the advantage of pre-allocating memory in case the condition is often met...
A = NaN(100,1)
for ii = 0:99
if rand > 0.5 % some condition
A(ii+1) = ii; % some value
end
end
A(isnan(A)) = []; % remove unused elements
Appending to the array. This avoids making A way too large if appending is unlikely...
A = []; % empty array
for ii = 0:99
if rand > 0.5 % some condition
A(end+1, 1) = ii; % some value. Equivalent to 'A = [A; ii];'
end
end
A better, and more Matlab-esque way of doing this would be to vectorise your conditional function. This way you avoid looping and allocation issues...
ii = 0:99;
A = ii(rand(100, 1) > 0.5);
You can use any Boolean function you like as an indexing array, as long as it returns a logical array with the same number of elements as the array you're indexing (ii here) or integer indices of the elements to choose.
The most efficient implementation of such C++ code would be
i = 0:99;
A = i(complicatedBoolFunction(i));
Anyway you can grow an array with concatenation, which is (or was) usually not recommended, like the following
A = [];
for i = 0:99
if (complicatedBoolFunction(i))
A = [A i];
end
end
or much more efficiently like this:
A = [];
for i = 0:99
if (complicatedBoolFunction(i))
A(end + 1) = i;
end
end

Applying a function on sorted array

Taken from the google interview question here
Suppose that you have a sorted array of integers (positive or negative). You want to apply a function of the form f(x) = a * x^2 + b * x + c to each element x of the array such that the resulting array is still sorted. Implement this in Java or C++. The input are the initial sorted array and the function parameters (a, b and c).
Do you think we can do it in-place with less than O(n log(n)) time where n is the array size (e.g. apply a function to each element of an array, after that sort the array)?
I think this can be done in linear time. Because the function is quadratic it will form a parabola, ie the values decrease (assuming a positive value for 'a') down to some minimum point and then after that will increase. So the algorithm should iterate over the sorted values until we reach/pass the minimum point of the function (which can be determined by a simple differentiation) and then for each value after the minimum it should just walk backward through the earlier values looking for the correct place to insert that value. Using a linked list would allow items to be moved around in-place.
The quadratic transform can cause part of the values to "fold" over the others. You will have to reverse their order, which can easily be done in-place, but then you will need to merge the two sequences.
In-place merge in linear time is possible, but this is a difficult process, normally out of the scope of an interview question (unless for a Teacher's position in Algorithmics).
Have a look at this solution: http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f04/Artikler/04/Huang88.pdf
I guess that the main idea is to reserve a part of the array where you allow swaps that scramble the data it contains. You use it to perform partial merges on the rest of the array and in the end you sort back the data. (The merging buffer must be small enough that it doesn't take more than O(N) to sort it.)
If a is > 0, then a minimum occurs at x = -b/(2a), and values will be copied to the output array in forward order from [0] to [n-1]. If a < 0, then a maximum occurs at x = -b/(2a) and values will be copied to the output array in reverse order from [n-1] to [0]. (If a == 0, then if b > 0, do a forward copy, if b < 0, do a reverse copy, If a == b == 0, nothing needs to be done). I think the sorted array can be binary searched for the closest value to -b/(2a) in O(log2(n)) (otherwise it's O(n)). Then this value is copied to the output array and the values before (decrementing index or pointer) and after (incrementing index or pointer) are merged into the output array, taking O(n) time.
static void sortArray(int arr[], int n, int A, int B, int C)
{
// Apply equation on all elements
for (int i = 0; i < n; i++)
arr[i] = A*arr[i]*arr[i] + B*arr[i] + C;
// Find maximum element in resultant array
int index=-1;
int maximum = -999999;
for (int i = 0; i< n; i++)
{
if (maximum < arr[i])
{
index = i;
maximum = arr[i];
}
}
// Use maximum element as a break point
// and merge both subarrays usin simple
// merge function of merge sort
int i = 0, j = n-1;
int[] new_arr = new int[n];
int k = 0;
while (i < index && j > index)
{
if (arr[i] < arr[j])
new_arr[k++] = arr[i++];
else
new_arr[k++] = arr[j--];
}
// Merge remaining elements
while (i < index)
new_arr[k++] = arr[i++];
while (j > index)
new_arr[k++] = arr[j--];
new_arr[n-1] = maximum;
// Modify original array
for (int p = 0; p < n ; p++)
arr[p] = new_arr[p];
}

Basic MATLAB variable manipulation

I have a dwc = [3001 x 2 double] which more or less is a sin function, I have a for loop finding top values in dwc(:,2). Lets say that there is a top value in dwc(531,2) which way is best way or what is easy to take dwc(531,1) and dwc(531,2) and make an M = [num_of_top_points x 2 double]?
For the following loop, what do I do?
j = 0;
for i = 2:size(dwcL01,1)-1
if dwcL01(i,2) > dwcL01(i-1,2) && dwcL01(i,2) > dwcL01(i+1,2)
j = j+1;
?? = dwcL01(i,:);
end
end
This is how you complete your loop
j = 0;
M = [];
for i = 2:size(dwcL01,1)-1
if dwcL01(i,2) > dwcL01(i-1,2) && dwcL01(i,2) > dwcL01(i+1,2)
j = j+1;
M(j, :) = dwcL01(i, :);
end
end
But you could do this much more efficiently by vectorizing
%//Some example data
x = -4*pi:0.5:4*pi;
y = cos(x);
dwcL01 = [x(:), y(:)]; %// (:) just makes it a column
%// Finding the peaks using diff and sign. Note that I add the first element to the beginning as diff reduces the size by one so this prevents offsetting
F = diff(sign(diff([dwcL01(1,2);dwcL01(:,2)]))) < 0;
M = [dwcL01(F,:)', dwcL01(F,:)'];
plot(x, y, M(:,1), M(:,2), '*r')
How that works is first we find the difference of each element consecutive element pair. Now when the sign changes, that means we've hit a max or min. If the sign change is negative then the gradient went from positive to negative which is a max. So I use diff(sign()) to find the points where the sign changes and then > 0 to create a logical matrix with false everywhere expect for the max. Then I use logical indexing to extract the max.
You could append it to a matrix (let's call it dwcL01_max) - this isn't the fastest way because the matrix size changes each loop but it works:
dwcL01_max = [dwcL01_max dwcL01(i,:)];
The other option would be to use the builtin findpeaks (from the signal proc toolbox)
[~, dwcL01_peaks] = findpeaks(dwcL01(:,2));
dwcL01_max = dwcL01(dwcL01_peaks, :);

Resources