Matlab delete specific elements from an array - arrays

I have for example a=[1 2 3 4 5 6 7 8 9 10]; and I have to delete each 2 following numbers from 3.
like at the end it should be a=[1 4 7 10];
How to do this without a for loop.
And also if there is a way to guarantee that at the end the resulting array will have exact number of entries, like here it should be a with 4 entries at the end.
But for example we have b=[1 2 3 4 5 6 7 8 9 ]; and if I want make sure that at the end I still have 4 entries in the rest array, so that b can't be equal to [1 4 7] because I need 4 entries for sure.

You can use indexing for this:
A = 1:10;
B = A(1:3:end)
B =
[1 4 7 10]
Or, if you really want to remove elements:
A = 1:10;
A(2:3:end) = [];
A(3:3:end) = [];
For your second question regarding length checking, it's unclear what you're asking. Would an if comparison be enough ?
if numel(A) ~= 4
% ... Handle unexpected values here
end
Best,

As you mentioned in the question and in the comments that you need 4 elements at the end and if elements are less than 4 then you want to include the last element/s of b, the following should work:-
b=[1 2 3 4 5 6 7 8 9]
b_req=b(1:3:end);
temp=length(b_req);
if temp<4 b_req(end+1:4)=b(end-3+temp:end); % for including the elements of b so that total elements are 4 at the end
elseif temp>4 b_req=b_req(1:4); % for removing the extra elements
end
b_req
Output:-
b =
1 2 3 4 5 6 7 8 9
b_req =
1 4 7 9
and
if instead b=[1 2 3 4 5 6 7 8 9 10]; then the same code gives what you require, i.e. b_req = [1 4 7 10]

This code speaks for itself:
a = 1:15; % some vector
% returns every third element after the first one:
third_elemets = a(1:3:end);
% returns the missing elements for the vector to be in size 4 from the end of a
last_elements = a(end-3+length(third_elemets):end);
% take maximum 4 elements from a
logic_ind = true(min(4,length(third_elemets)),1);
% and concatanate them with last_elements (if there are any)
a = [third_elemets(logic_ind) last_elements]
and under the assumption that whenever there are less than 4 elements you simply take the last one(s) - it should always work.

Related

Find an element in a specific row and column in a 2D array

I'm having trouble in looking for an element in a specific.
I have the array
A = [ 1 2 3 7 2 ; 2 8 5 7 2; 1 9 8 4 1; 8 7 2 10 9; 10 9 4 3 8]
I just want to get the index of A(3,4) for the element of 4. However my code spits out the two locations of the element 4, which is A(5,3) and A(3,4).
I used [row, col] = find(E==4)
Use
[row, col] = find(E==4, 1)
The second parameter is the number of elements you want to find. Find more details at https://www.mathworks.com/help/matlab/ref/find.html
Matlab searches a matrix in column-by-column order. If you want to find the first element by rows, you could transpose E before calling find. But you need to swap the resulting indices then:
[col, row] = find(E'==4, 1)
Here's a lengthier, iterative way to find the first index:
A = [ 1 2 3 7 2 ;...
2 8 5 7 2;...
1 9 8 4 1;...
8 7 2 10 9;...
10 9 4 3 8];
[a,b] = size(A);
for i = 1:a
for j = 1:b
if A(i,j) == 4
break
end
end
if A(i,j) == 4
break
end
end
index = [i,j]
It returned [3, 4] for me.

Pairs of random numbers Matlab

I am trying to generate random numbers between 1 and 6 using Matlab's randperm and calling randperm = 6.
Each time this gives me a different array let's say for example:
x = randperm(6)
x = [3 2 4 1 5 6]
I was wondering if it was possible to create pairs of random numbers such that you end up with x like:
x = [3 4 1 2 5 6]
I need the vector to be arranged such that 1 and 2 are always next to each other, 3 and 4 next to each other and 5 and 6 next to each other. As I'm doing something in Psychtoolbox and this order is important.
Is it possible to have "blocks" of random order? I can't figure out how to do it.
Thanks
x=1:block:t ; %Numbers
req = bsxfun(#plus, x(randperm(t/block)),(0:block-1).'); %generating random blocks of #
%or req=x(randperm(t/block))+(0:block-1).' ; if you have MATLAB R2016b or later
req=req(:); %reshape
where,
t = total numbers
block = numbers in one block
%Sample run with t=12 and block=3
>> req.'
ans =
10 11 12 4 5 6 1 2 3 7 8 9
Edit:
If you also want the numbers within each block in random order, add the following 3 lines before the last line of above code:
[~, idx] = sort(rand(block,t/block)); %generating indices for shuffling
idx=bsxfun(#plus,idx,0:block:(t/block-1)*block); %shuffled linear indices
req=req(idx); %shuffled matrix
%Sample run with t=12 and block=3
req.'
ans =
9 8 7 2 3 1 12 10 11 5 6 4
I can see a simple 3 step process to get your desired output:
Produce 2*randperm(3)
Double up the values
Add randperm(2)-2 (randomly ordered pair of (-1,0)) to each pair.
In code:
x = randperm(3)
y = 2*x([1 1 2 2 3 3])
z = y + ([randperm(2),randperm(2),randperm(2)]-2)
with result
x = 3 1 2
y = 6 6 2 2 4 4
z = 6 5 2 1 3 4

Replace Value in Array with Previous Value Matlab

Original Question
So if I have an array, s:
s= [4 5 2 5 8 4 11 6]
How would I go about replacing any number greater than 6 to be equal to the previous number. Giving s to be:
s=[4 5 2 5 5 4 4 6]
Updated Question
I want to check if the number is at least double the previous number, and if so to replace with the previous number. Using the a different example to above, s:
s= [8 9 3 6 7 2 5]
Would be replaced with, s:
s= [8 9 3 3 3 2 2]
Using the cummax function (introduced in R2014b):
s = s(cummax((s<=6).*(1:numel(s))));
Example:
>> s = [5 7 9 2 5 8 4 11 6]
s =
5 7 9 2 5 8 4 11 6
>> s = s(cummax((s<=6).*(1:numel(s))))
s =
5 5 5 2 5 5 4 4 6
All you need to do is, iterate over all the values of your array and check if current value is greater than twice the previous value (you can replace the > with >= (greater than or equal to) if that's what you need. And whenever your required condition is met, you just need to copy value from s(i-1) i.e. the previous index to s(i) i.e. current place.
Your loop starts from i=2 instead of 1 because there is no previous value to check in case of i=1. In MALTAB indexing starts from i instead of 0 as in most languages.
s = [4 2 7 5 1];
for i=2:numel(s)
if s(i) > 2*s(i-1)
s(i) = s(i-1);
end
end

Compare Values in Array on Specific Indexes in Matlab

how to Compare Values in Array on Specific Indexes in Matlab?
Suppose:
A= [2 2 3 3 3 4 4 4 5 5 6 6 7 8 8]
so i want to Find that
on index 2,3,4,5,6 values or same or not ?
Note: Index can be Dynamically Entered.
Number(length) of Values in Array also can be changed..
To check if they are all equal: use diff to subtract pairs of values, and then check if all those differences are 0.
A = [2 2 3 3 3 4 4 4 5 5 6 6 7 8 8];
ind = [2 3 4 5 6];
result = ~any(diff(A(ind)));
This is faster than using unique. With A and ind as in your example,
>> tic
for cont = 1:1e5
result = ~any(diff(A(ind)));
end
toc
tic
for cont = 1:1e5
result=numel(unique(A(ind)))==1;
end
toc
Elapsed time is 0.371142 seconds.
Elapsed time is 4.754007 seconds.
Hey this should do the trick:
A= [2 2 3 3 3 4 4 4 5 5 6 6 7 8 8];
B= [1,3,5];
C=A(B);
result=numel(unique(C))==1;
Here A is your data.
B is the index vector.
C contains the elements corresponding to the index vector.
result is 1 if all values were the same and 0 otherwise.
You can even "shorten" the code further by joining the two line:
result=numel(unique(A(B)))==1;
There are some ways, it depends on your taste.
For example, if the variable indexing contain the corresponding indexes:
unique(A(indexing));
will give you a vector with the unique elements in the sub-vector A(indexing). Then you just need to check the length:
length(unique(A(indexing))) == 1
I would avoid the use of numel when the function length is available (it is much more clearer what you are trying to achieve).
Other option is to compare the first element to the rest of the element in the sub-vector:
sub_vector = A(indexing);
all(sub_vector == sub_vector(1));
The second option assumes that the sub-vector will never be empty!

Vectorized Reshaping of Columns in an Array

I have an array A, and want to reshape the last four elements of each column into a 2x2 matrix. I would like the results to be stored in a cell array B.
For example, given:
A = [1:6; 3:8; 5:10]';
I would like B to contain three 2x2 arrays, such that:
B{1} = [3, 5; 4, 6];
B{2} = [5, 7; 6, 8];
B{3} = [7, 9; 8, 10];
I can obviously do this in a for loop using something like reshape(A(end-3:end, ii), 2, 2) and looping over ii. Can anyone propose a vectorized method, perhaps using something similar to cellfun that can apply an operation repeatedly to columns of an array?
The way I do this is to look at the desired indices and then figure out a way to generate them, usually using some form of repmat. For example, if you want the last 4 items in each column, the (absolute) indices into A are going to be 3,4,5,6, then add the number of rows to that to move to the next column to get 9,10,11,12 and so on. So the problem becomes generating that matrix in terms of your number of rows, number of columns, and the number of elements you want from each column (I'll call it n, in your case n=4).
octave:1> A = [1:6; 3:8; 5:10]'
A =
1 3 5
2 4 6
3 5 7
4 6 8
5 7 9
6 8 10
octave:2> dim=size(A)
dim =
6 3
octave:3> n=4
n = 4
octave:4> x=repmat((dim(1)-n+1):dim(1),[dim(2),1])'
x =
3 3 3
4 4 4
5 5 5
6 6 6
octave:5> y=repmat((0:(dim(2)-1)),[n,1])
y =
0 1 2
0 1 2
0 1 2
0 1 2
octave:6> ii=x+dim(1)*y
ii =
3 9 15
4 10 16
5 11 17
6 12 18
octave:7> A(ii)
ans =
3 5 7
4 6 8
5 7 9
6 8 10
octave:8> B=reshape(A(ii),sqrt(n),sqrt(n),dim(2))
B =
ans(:,:,1) =
3 5
4 6
ans(:,:,2) =
5 7
6 8
ans(:,:,3) =
7 9
8 10
Depending on how you generate x and y, you can even do away with the multiplication, but I'll leave that to you. :D
IMO you don't need a cell array to store them either, a 3D matrix works just as well and you index into it the same way (but don't forget to squeeze it before you use it).
I gave a similar answer in this question.

Resources