Match length of two unequal arrays in MATLAB? - arrays

Suppose I have 3 arrays of different length:
A[1 2 3 4 5 6]; B[1 2 4], C[0 1 5 6]
the MAXIMUM length the three arrays is 6.
So I want B and C to have 6 elements too. Furthermore, the last "filled" elements of new array should be the last element of the original array
At the end, new B should look like [1 2 4 4 4 4], C should look like [0 1 5 6 6 6], how do I implement this?
Thanks a lot!

You can do this using MATLAB's indexing operators. If you assign to elements past the end of an array, MATLAB will grow the array. For vectors (as in this case), you only need to specify a single subscript because the direction to extend the array is not ambiguous.
I'd do it like this - this doesn't assume that you know up-front which of the arrays is the largest. I'm using numel to compute the number of elements in each vector. I'm also relying on the fact that for one of the arrays, end+1:maxLen is an empty range, so no modifications are made in that case.
maxLen = max([numel(A), numel(B), numel(C)]);
A(end+1:maxLen) = A(end)
B(end+1:maxLen) = B(end)
C(end+1:maxLen) = C(end)

Related

MATLAB - Get every N elements in a vector

I have an array
a = [1 2 3 4 5 6 7 8]
I want to get every group of 4
so the result is as such
[1 2 3 4]
[5 6 7 8]
I do not know how many elements there will be but I know it is divisible by 4
so something like a(1:4) and a(5:8) wont work, I can use a loop, but is there a way to not use a loop?
For an unknown number of elements in a you can use reshape you just need to figure out how many rows you will have in the final matrix or (better for your case) the number of columns.
a = 1:4*10;
a2 = reshape(a, 4, []).';
If you went the rows routine you would do this.
a = 1:4*10;
a2 = reshape(a, [], numel(a) / 4).';
You just need to be sure that a has the proper number of elements. numel simply tells you the total element count.

Trying to compare elements of on array with every element of another array in matlab

I'm using Matlab, and I'm trying to come up with a vectorized solution for comparing the elements of one array to every element of another array. Specifically I want to find the difference and see if this difference is below a certain threshold.
Ex: a = [1 5 10 15] and b=[12 13 14 15], threshold = 6
so the elements in a that would satisfy the threshold would be 10 and 15 since each value comes within 6 of any of the values in b while 1 and 5 do not. Currently I have a for loop going through the elements of a and subtracting an equivalently sized matrix from b (for 5 it would be a = [5 5 5 5]). This obviously takes a long time so I'm trying to find a vectorized solution. Additionally, the current format I have my data in is actually cells where each cell element has size [1 2], and I have been using the cellfun function to perform my subtraction. I'm not sure if this complicates the solution of each [1 2] block with the [1 2] block of the second cell. A vectorized solution response is fine, there is no need to do the threshold analysis. I just added it in for a little more background.
Thanks in advance,
Manwei Chan
Use bsxfun:
>> ind = any(abs(bsxfun(#minus,a(:).',b(:)))<threshold)
ind =
0 0 1 1
>> a(ind)
ans =
10 15

Merge arrays with unequal number of columns

I have around 100 1D arrays I'd like to merge to a matrix.
The arrays have 140 to 180 columns.
Is it possible to merge these 1 x (140-180) arrays to a matrix with a dimension of 100 (amount of arrays) x 180 ?
All the arrays contain numbers. I want to expand the 1x140 array to a 1x180 array by means of interpolation.
In a simplified form, it should be something like this:
A = [1 5 7 8 3]
B = [1 3 5]
result=
[1 5 7 8 3
1 2 3 4 5]
The array B (1x3) is expanded to an 1x5 matrix. And the values in between are interpolated.
Basically, I thought of using "vertcat" after all arrays are expanded by a same amount of columns.
Thanks in advance,
Koen
How about this?
array = {[1 5 7 8 3],[1 3 5]}; % example data
N = 5; % desired length (180 in your case)
aux = cellfun(#(v) interp1(linspace(0,1,length(v)),v,linspace(0,1,N)), array, 'uni', false);
result = cat(1,aux{:});
It uses linear interpolation. For your example, this gives
>> result
result =
1 5 7 8 3
1 2 3 4 5
Note that linear interpolation modifies all values of the vector except first and last, in general. For example, with N=5 the vector [1 3 4 5] would get interpolated to [1 2.5 3.5 4.25 5]. You could use other forms of interpolation by passing an extra argument to interp1, see help interp1.

MATLAB: compare elements in arrays

suppose there are arrays A and B, both of which can have any arbitrary numbers and size. for example
A=[1 2 3]
B=[4 8 52 7 10]
i was wondering if there was any way to check if any of the elements in A are contained in B without using a loop? Once again, the numbers and size of the array will be arbitrary so i can't hard code it. Any help and input would be appreciated. Thanks!
You mean like this:
A=[1 2 3]; B=[4 8 52 7 10]
ismember(A,B)
ans =
0 0 0
Add to #NasserM.Abbasi: ismember will work regardless shapes and sizes, it is always element-wise. So if you have A=[1 2; 3 4] and B=[1 3; 4 2; 1 2],
then ismember will return :
ismember(A,B); % -> [1 1; 1 1] due to element-wise membership check
ismember(A,B, 'rows'); % -> [1 0] since it checks row-wise.
use ismember carefully according to the possible shapes in A and B.

Easiest way to create arrays based on repeating character positions

I want to group my elements using the repeated segments in the array. The breaking is basically depend on where the repeated segments are, in my real data contains ~10000 elements and I want to know if there is a easier way to do that.
Here is a short example to clarify what I want:
Let's say I have an array,
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
What I want is to break A into [1 5 3],[6 9], and [9 5 2];
What is the easiest to code this using matlab??
Thanks.
For a vectorized solution, you can find out the places where either forward or backward differences to the neighbor are zero, and then use bwlabel (from the Image Processing Toolbox) and accumarray to gather the data.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
d = diff(A)==0;
%# combine forward and backward difference
%# and invert to identify non-repeating elments
goodIdx = ~([d,false]|[false,d]);
%# create list of group labels using bwlabel
groupIdx = bwlabel(goodIdx);
%# distribute the data into cell arrays
%# note that the first to inputs should be n-by-1
B = accumarray(groupIdx(goodIdx)',A(goodIdx)',[],#(x){x})
EDIT
Replace the last two lines of code with the following if you want the repeating elements to appear in the cell array as well
groupIdx = cumsum([1,abs(diff(goodIdx))]);
B = accumarray(groupIdx',A',[],#(x){x})
EDIT2
If you want to be able to split consecutive groups of identical numbers as well, you need to calculate groupIdx as follows:
groupIdx = cumsum([1,abs(diff(goodIdx))|~d.*~goodIdx(2:end)])
Here is a solution that works if I understand the question correctly. It can probably be optimised further.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
% //First get logical array of non consecutive numbers
x = [1 (diff(A)~=0)];
for nn=1:numel(A)
if ~x(nn)
if x(nn-1)
x(nn-1)=0;
end
end
end
% //Make a cell array using the logical array
y = 1+[0 cumsum(diff(find(x))~=1)];
x(x~=0) = y;
for kk = unique(y)
B{kk} = A(x==kk);
end
B{:}

Resources