Extract equal distance points from array - Matlab - matlab

I have an array of X,Y coordinates (closed object) of different sizes (numArrayLength, e.g., 25) and I wish to extract specific equally distances points based on a changeable number (subSetNum).
I have few issues that I will appreciate a help:
As the 1st and last content in the array are similar how can I avoid this point duplication?
I have a calculation issue, for example when I set subSetNum to 8 I get 1 4 7 10 13 16 19 22 25 but when it is set to 7 I get 1 5 9 13 17 21 25. Why?
Is there a way to do it without the loop?
Thanks.
Script:
clc;
clear;
numArrayLength=25; % Length of the array
subSetNum=8; % Selection points
numArray=rand(numArrayLength,2); % Array declaration, Y coordinate
numArray(numArrayLength)=numArray(1) %% Close object so Y(1) and Y(numArrayLength) are the same
numArray = numArray(1:end-1,:)
extractPoint=round(numArrayLength/subSetNum); %Number of points to extract
extractPointIndex=1:extractPoint:numArrayLength %Array index to extract
for n = 1:size(extractPointIndex)
numArray(extractPointIndex())
end

Related

how to plot cell array with (31*1) dimensions in matlab?

I have a cell array with one column and thirty one rows, and I'm going to plot the array so that the horizontal axis changes from one to thirty one, and the vertical axis corresponds to values like peer to inside cell.
my cell array :
data2 =
31×1 cell array
'2.4392E-09' '2.6506E-09' '3.0690E-09' '4.0424E-09' '7.1719E-09'
'1.8084E-08' '6.0006E-08' '2.1621E-07' '7.7861E-07' '2.6695E-06'
'8.4323E-06' '2.3340E-05' '5.1783E-05' '1.1155E-04' '2.6871E-04'
'3.4549E-04' '2.6871E-04' '1.1155E-04' '5.1783E-05' '2.3340E-05'
'8.4323E-06' '2.6695E-06' '7.7861E-07' '2.1621E-07' '6.0006E-08'
'1.8084E-08' '7.1719E-09' '4.0424E-09' '3.0690E-09' '2.6506E-09'
'2.4392E-09'
and
i2 =
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
and part of my code for plot is:
i=1:1:31
data2=data(:,1)
i2=transpose(i);
i2=i2(:,1)
plot(i2,data2)
str2double converts numbers, stored as characters in cells of data2, to numeric (double) type. It is directly applicable on cell-arrays. If the required x-axis is the same as 1:numel(data2) then specifying it is not needed. So,
plot(str2double(data2));
This question aims at the very basics of MATLAB.
You have strings in a cell array. Access the content of cells with {} and convert it with str2doubleto numbers.
Further, keep the code clean and readable (data, data2 and i,i2) are not good variable names in no language... You don't need to transpose the vector but if you do, you can use the shortcut .'. Note that the . indicates that it is not a complex transpose
idx = 1:size(data,1)
cstr = data(:,1); % call the content of cells with {} / call a cell element with ()
num = str2double(cstr); % convert string to doubles/numbers
plot(idx.',num) % .' transposes an array/vector but in fact, you don't need it here

dynamic increment step to define a vector in matlab

I would like to know is there anyway to do the following statement in matlab?
10: 2to power(1,2,3):18
I want to create the following vector and I need to have a dynamic increment step which is 2 to the power of (1,2,3).
a=[10,12,14,18]
I tried
10:2.^[1,2,3]:18
and
10:2.^[1;2;3]:18
but it takes 2^1 as increment step.
No you cannot have a dynamic increment value in MATLAB.
The MATLAB way of doing this would be to create the array 2.^[1 2 3] and add it to the 10 and concatenate that with 10 to construct your vector.
a = [10 10 + (2.^[1 2 3])]
% 10 12 14 18
If you wanted, you could write a function to create these arrays.
function out = pow2increment(start_value, end_value)
% Figure out how many powers of 2 we need for this range
upper_limit = floor(log2(end_value - start_value));
% Construct the array
out = [start_value, start_value + 2.^(1:upper_limit)];
end
Or as an anonymous function
pow2increment = #(a,b)[a, a + 2.^(1:floor(log2(b - a)))];
pow2increment(10, 18)
% 10 12 14 18

How to get unique pairs of numbers in matlab where both numbers have not repeated in the matrix before

I have an input matrix as below
all = [12 16;12 13;8 14;14 19;3 6;8 6;13 25;25 14;7 2];
I need the following output
output = [12 16;8 14;3 6;13 25;7 2];
The explanation for the output is as follows.
First row of input i.e. 12 16 is the first row in output as both the numbers have never been repeated before in the output matrix (obviously).
Second row of input i.e 12 13 is not needed as the number 12 is present in first row of output i.e repeated
Third row of input i.e 8 14 is second row of output as both the numbers have never been repeated before in the output matrix.
Fourth row of input i.e 14 19 is not needed as the number 14 is present in output i.e repeated
On similar lines
3 6 needed as both are not repeated,
8 6 not needed as both 8 and 6 are repeated,
13 25 needed as both are not repeated
25 14 not needed as both are repeated
7 2 needed as both are not repeated
I am not able to get any ideas to start. Any help will be appreciated.
Thanks!
One Liner Solution
res = all(arrayfun(#(ii) isempty(intersect(all(1:ii-1,:),all(ii,:))),1:size(all,1)),:);
Result
res =
12 16
8 14
3 6
7 2
Explanation
let's divide the one-liner into a more detailed and documented chunk of code:
%defines a function which validates for each index wheter the row is
%completely unique are not.
uniqueRowIndicator = #(ii) isempty(intersect(all(1:ii-1,:),all(ii,:)));
%finds all the unique row in the matrix
inds = arrayfun(uniqueRowIndicator,1:size(all,1));
%extracts the result from the returned indices
res = all(inds,:);
This assumes that if a row contains two equal values they count as repeated and thus the row should be removed.
Don't use all as a variable name, because that shadows a function:
A = [12 16;12 13;8 14;14 19;3 6;8 6;13 25;25 14;7 2]; % input matrix
[~, u] = unique(A.', 'first'); % unique values of linearized transposed A.
% In recent Matlab versions you an remove 'first '
M = false(flip(size(A))); % initiallize mask of values to be kept
M(u) = true; % fill values
output = A(all(M,1),:); % keep rows that only have non-repeated values
This gives
output =
12 16
8 14
3 6
7 2

Extract the same part of slices of a 3D matrix by using linear index

Indeed, my problem is a succession of my previous problem:
1) Extract submatrices, 2) vectorize and then 3) put back
Thanks to Dan and his ideas works perfectly for the purpose.
My new problem is this:
If I have a 3D matrix, 8 by 8 by 12, e.g. A = randn(8,8,12).
Let's see the linear index of the first slice:
From Dan's solution, I understand that A[4:6, 4:6, :] can extract the corresponding parts of all slices.
However, going back to my real situations, extracting parts by actually counting rows and columns seem not suit my purpose because my matrix size is huge and I do have many sub-matrices to be extracted.
So, I prefer to work on linear index and want to ask if there are any ways to work with this possibility.
Here is my trial:
By defining sub_group = [28 29 30 36 37 38 44 45 46], then A(sub_group) can extract sub-matrix from the first slice of the 3D matrix, A.
I understand that A(sub_group + 8*8*(n-1)) can extract the sub-matrix from the nth slice.
I aim to only work with my sub_group and then extract the same part of every slice.
Most importantly, I have to put back the sub-matrices after updating their values.
So, is there are any quick syntax for matlab to work for my purpose?
I appreciate for your help.
Approach #1
For cases like this when you need to calculate linear indices, you can use bsxfun as shown here -
%// Store number of rows in A as a variable
M = size(A,1)
%// Get start and offset linear indices for the first slice and thus sub_group
start_idx = (colstart-1)*M + rowstart
offset_idx = bsxfun(#plus,[0:rowstop - rowstart]', [0:colstop-colstart]*M) %//'
sub_group = reshape(start_idx + offset_idx,1,[])
%// Calculate sub_groups for all 3D slices
all_sub_groups = bsxfun(#plus,sub_group',[0:size(A,3)-1]*numel(A(:,:,1)))
Sample run -
A(:,:,1) =
0.096594 0.52368 0.76285 0.83984 0.27019
0.84588 0.65035 0.57569 0.42683 0.4008
0.9094 0.38515 0.63192 0.63162 0.55425
0.011341 0.6493 0.2782 0.83347 0.44387
A(:,:,2) =
0.090384 0.037262 0.38325 0.89456 0.89451
0.74438 0.9758 0.88445 0.39852 0.21417
0.032615 0.52234 0.25502 0.62502 0.0038592
0.42974 0.90963 0.90905 0.5676 0.88058
rowstart =
2
rowstop =
4
colstart =
3
colstop =
5
sub_group =
10 11 12 14 15 16 18 19 20
all_sub_groups =
10 30
11 31
12 32
14 34
15 35
16 36
18 38
19 39
20 40
Approach #2
For a quick syntax based solution, sub2ind could be suggested here. The implementation would look something like this -
[X,Y] = ndgrid(rowstart:rowstop,colstart:colstop);
sub_group = sub2ind(size(A(:,:,1)),X,Y);
[X,Y,Z] = ndgrid(rowstart:rowstop,colstart:colstop,1:size(A,3));
all_sub_groups = sub2ind(size(A),X,Y,Z);

MATLAB: interpolate vector

How can I interpolate a vector in MATLAB?
For example, I have the following matrix:
M=
1 10
2 20
3 30
4 40
The first column of M denotes the independent parameter of x coordinate while the second column of M denotes the output or y coordinate.
I also have the following input vector:
a =
2.3
2.1
3.5
For each value of a, I wish to determine what the output interpolated result would be. In this case, given a, I wish to return
23
21
35
Here's the answer to the question after the edit, i.e. "how to interpolate"
You want to use interp1
M = [1 10;2 20;3 30;4 40];
a = [2.3;2.1;3.5;1.2];
interpolatedVector = interp1(M(:,1),M(:,2),a)
interpolatedVector =
23
21
35
12
Here's the answer to the question "find the two closest entries in a vector", i.e. the original question before the edit.
x=[1,2,3,4,5]'; %'#
a =3.3;
%# sort the absolute difference
[~,idx] = sort(abs(x-a));
%# find the two closest entries
twoClosestIdx = idx(1:2);
%# turn it into a logical array
%# if linear indices aren't good enough
twoClosestIdxLogical = false(size(x));
twoClosestIdxLogical(twoClosestIdx) = true;
twoClosestIdxLogical =
0
0
1
1
0