force constant value using position of a vector - matlab

I have a vector with some positions
position = [2;5;10;12;18];
I would like to create a vector that looks like that
output = [1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0];
It means I take the difference between each value of position and in 'output' I put the number 1 for the first difference number and after 0 for the second difference number and so on..
diff = [3;5;2;6];
So, in output I have 3 ones, then 5 zeros, then 2 ones, then 6 zeros...
Thank you for you help.

You can also use repelem
a = diff(position);
b = mod(1:length(a),2);
repelem(b,a(:)')

How about this?
result = mod(sum(bsxfun(#lt, position(1):position(end)-1, position), 1) + 1, 2);
I'll let you figure out how it works.

Related

Matlab: enter same vector repeatedly to matrix using logical indexing

I would like to enter the same vector of numbers repeatedly to an existing matrix at specific (row) logical indices. This is like an extension of entering just a single number at all logical index positions (at least in my head).
I.e., it is possible to have
mat = zeros(5,3);
rowInd = logical([0 1 0 0 1]); %normally obtained from previous operation
mat(rowInd,1) = 15;
mat =
0 0 0
15 0 0
0 0 0
0 0 0
15 0 0
But I would like to do sth like this
mat(rowInd,:) = [15 6 3]; %rows 2 and 5 should be filled with these numbers
and get an assignment mismatch error.
I want to avoid for loops for the rows or assigning vector elements single file. I have the strong feeling there is an elementary matlab operation that should be able to do this? Thanks!
The problem is that your indexing picks two rows from the matrix and tries to assign a single row to them. You have to replicate the targeted row to fit your indexing:
mat = zeros(5,3);
rowInd = logical([0 1 0 0 1]);
mat(rowInd,:) = repmat([15 6 3],sum(rowInd),1)
This returns:
mat =
0 0 0
15 6 3
0 0 0
0 0 0
15 6 3

Matlab: Can I create a matrix with unknown number of dimensions?

Normally a matrix has 2 dimensions, but there doesn't seem to be a limit on the number of dimensions a matrix may have in MATLAB.
To create a 4-dimensional matrix, for example, I can do this:
>> x = zeros(2,2,2,2)
x(:,:,1,1) =
0 0
0 0
x(:,:,2,1) =
0 0
0 0
x(:,:,1,2) =
0 0
0 0
x(:,:,2,2) =
0 0
0 0
Is there a way to create a matrix of which the number of dimensions is only known at runtime?
You could call zeros like this:
x = zeros([2 2 2 2])
Hence, you can customize the input array as you want.
For example: to create a 2x2x2x2x2 matrix (where D = 5, the number of dimensions):
D = 5;
x = zeros(zeros(1, D) + 2)
Rafael's answer hits the nail on the head. But there's also a general way to do this sort of thing even when the function doesn't have an overload for something like a vector input as in the case of zeros. You can use a cell array like so:
>> dims = {2,2,2,2};
>> zeros(dims{:})
ans(:,:,1,1) =
0 0
0 0
ans(:,:,2,1) =
0 0
0 0
ans(:,:,1,2) =
0 0
0 0
ans(:,:,2,2) =
0 0
0 0
I've found this approach to be very useful for other functions.
Edit:
This approach is more robust. Here's another example:
imginfo = { rand(40), [0 1], 'Colormap', colormap(jet) };
figure, imshow(a{:});

Count the number of the first zero elements

I would line to find the number of the first consecutive zero elements. For example in [0 0 1 -5 3 0] we have two zero consecutive elements that appear first in the vector.
could you please suggest a way without using for loops?
V=[0 0 1 -5 3 0] ;
k=find(V);
Number_of_first_zeros=k(1)-1;
Or,
Number_of_first_zeros=find(V,1,'first')-1;
To solve #The minion comment (if that was the purpose):
Number_of_first_zeros=find(V(find(~V,1,'first'):end),1,'first')-find(~V,1,'first');
Use a logical array to find the zeros and then look at where the zeros and ones are alternating.
V=[1 2 0 0 0 3 5123];
diff(V==0)
ans =
0 1 0 0 -1 0
Create sample data
V=[1 2 0 0 0 3 5123];
Find the zeros. The result will be a logical array where 1 represents the location of the zeros
D=V==0
D =
0 0 1 1 1 0 0
Take the difference of that array. 1 would then represent the start and -1 would represent the end.
T= diff(D)
ans =
0 1 0 0 -1 0
find(T==1) would give you the start and find(T==-1) would give you the end. The first index+1 of T==1 would be the start of the first set of zeros and the first index of T==-1 would be the end of the first set of zeros.
You could find position the first nonzero element using find.
I=find(A, 1);
The number of leading zeros is then I-1.
My solution is quite complex yet it doesn't use the loops and it does the trick. I am pretty sure, that there is a more direct approach.
Just in case no one else posts a working solution here my idea.
x=[1 2 4 0 20 0 10 1 23 45];
x1=find(x==0);
if numel(x1)>1
x2=[x1(2:end), 0];
x3=x2-x1;
y=find(x3~=1);
y(1)
elseif numel(x1)==1
display(1)
else
display('No zero found')
end
x is the dataset. x1 contains the index of all zero elements. x2 contains all those indices except the first one (because matrix dimensions must agree, one zero is added. x3 is the difference between the index and the previous index of zeros in your dataset. Now I find all those differences which are not 1 (do not correspond to sequences of zeros) and the first index (of this data is the required result. The if case is needed in case you have only one or no zero at all.
I'm assuming your question is the following: for the following vector [0 0 1 -5 3 0], I would like to find the index of the first element of a pair of 0 values. Is this correct? Therefore, the desired output for your vector would be '1'?
To extend the other answers to find any such pairs, not just 0 0 (eg. 0 1, 0 2, 3 4 etc), then this might help.
% define the pattern
ptrn = [ 0 0 ];
difference = ptrn(2) - ptrn(1)
V = [0 0 1 -5 3 0 0 2 3 4 0 0 1 0 0 0]
x = diff(V) == difference
indices = find(x)
indices =
1 6 11 14 15

Convert digit to vector octave/matlab [duplicate]

This question already has answers here:
Construct this matrix based on two vectors MATLAB
(3 answers)
Closed 8 years ago.
I have a vector y = [0; 2; 4]
I want to convert each element of it into vector, where all elements are zero but element with index equal to digit is 1.
I'd like to do it without loops.
For example [0; 2; 4] should be converted to
[1 0 0 0 0 0 0 0 0 0;
0 0 1 0 0 0 0 0 0 0;
0 0 0 0 1 0 0 0 0 0]
(in this example vector first index is 0)
The usual trick with sparse can be used to simplify the process. Let n denote the desired number of columns. Then
result = full(sparse(1:numel(y), y+1, 1, numel(y), n));
For example, y = [0;2;4] and 10 produce
result =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
First you need to decide how many digits you want to represent each number. In your case, you have 10 digits per number, so let's keep that in mind.
Once you do this, it's just a matter of indexing each element in your matrix. In your case, you have 10 digits per number. As such, do something like this:
y = [0; 2; 4]; %// Your digits array
out = zeros(numel(y), 10); %// 10 digits per number
ind = sub2ind(size(out), [1:numel(y)].', y+1);
out(ind) = 1;
The output should look like this:
out =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
Let's go through this code slowly. y defines the digits you want per row of the output matrix. out allocates a matrix of zeroes where the number of rows is defined by how many digits you want in y. out will thus store your resulting matrix that you have shown us in your post.
The number of columns is 10, but you change this to be whatever you want. ind uses a command called sub2ind. This allows to completely vectorize the assignment of values in your out matrix and avoids a for loop. The first parameter is an array of values that defines how many rows and columns are in your matrix that you are trying to assign things to. In this case, it's just the size of out. The second and third parameters are the rows and columns you want to access in your matrix. In this case, the rows vary from 1 to as many elements as there are in y. In our case, this is 3. We want to generate one number per row, which is why it goes from 1 to 3. The columns denote where we want to set the digit to one for each row. As MATLAB indexes starting at 1, we have to make sure that we take y and add by 1. ind thus creates the column-major indices in order to access our matrix. The last statement finally accesses these locations and assigns a 1 to each location, thus producing our matrix.
Hope this helps!

Finding a vector within a vector

I have an (7,6) logical array, such as the following:
validY2_A =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 1 0 0
1 0 0 1 1 0
1 1 1 0 0 1
1 1 1 0 1 1
0 1 1 1 1 1
I want to create a (1,6) logical vector 'contig' that shows whether the above matrix has 3 contiguous ones in each column. For example, the outcome of this would be:
contig =
[1, 1, 1, 0, 0 ,1];
I've tried strfind but there are two issues with this, the first being that it is an array of columns (transposing either didn't help at all. or would require lots of extra code to use temporarily. The second issue is that because it is a logical array, if I change it to a string, the values all become true or false, and trying to get that to work has also been fruitless. Is there a method to search a column vector to find if another, specific column vector exists anywhere within it? I want to search each column for [1; 1; 1];
Thanks
How about
t = imfilter( validY2_A, ones(3,1) );
contig = any( t >= 3, 1 );
Alternatively (as suggested by #Dan):
t = conv2( validY2_A, ones(3,1), 'same');
contig = any( t >= 3, 1 );
As suggested by #GeorgeAprilis, one might need to convert the logical matrix validY2_A to double first:
validY2_A = double( validY2_A );
Here is a way that should be easy to understand:
idx1=1:end-2
idx2=2:end-1
idx3=3:end
Basically these indexes shift your matrix three times.
Now you just apply them:
any(validY2_A(idx1,:) & validY2_A(idx2,:) & validY2_A(idx3,:))
This is not too hard to generalize using a loop and shift function for example.