Simple enough question, but I'm not finding a simple solution:
I want to say, "is this vector 1, 4, 7, and then 5 of whatever number?"
For example:
[1,4,7,2,6,5,8,3]
...or:
[1,4,7,2,8,5,9,2]
The final five numbers can be anything, as long as they're numbers.
Thank you!
Subscript can itself be another vector in Matlab. So you can test any values in vector:
x=zeros(1,10);
x(1)=1;x(2)=2; x(3)=3;x(6)=4;x(9)=5;
x % x = 1 2 3 0 0 4 0 0 5 0
L=[1:3,6,9]; %subscipt of vector v
y=[1, 2, 3, 4, 5];
isequal(x(L),y) % ans = 1
You can test these two conditions separately and then combine them with and.
x1 = [1,4,7,2,6,5,8,3];
is147 = all(x1(1:3)==[1,4,7]);
and(is147,length(x1)==8)
I think, for a list, the last 5 numbers have to be numeric, but if not you can put in extra tests, such as isnumeric(). Also if the input changes between column and row vectors, you can force a row vector with x_col = x1(:)
Here is a solution that will check if your variable is a vector, isvector, verify it has a length of 8 and check that the first 3 elements are [1 4 7], isequal.
>> v = [1 4 7 2 6 5 8 3];
>> isvector(v) && numel(v) == 8 && isequal(v(1:3), [1 4 7])
ans =
1
>> v = [1 4 7 2 6 5 8];
>> isvector(v) && numel(v) == 8 && isequal(v(1:3), [1 4 7])
ans =
0
>> v = [9 4 7 2 6 5 8 3];
>> isvector(v) && numel(v) == 8 && isequal(v(1:3), [1 4 7])
ans =
0
>> v = [1 4 7 2; 6 5 8 3];
>> isvector(v) && numel(v) == 8 && isequal(v(1:3), [1 4 7])
ans =
0
Related
I am trying to index my matrix based on two conditions, I'll explain.
Let's say I have two matrices:
a = [7 3 4; 5 6 7; 4 8 0];
b = [1 9 8; 2 4 6; 6 1 6];
And a third matrix to index:
c = [1 2 3; 4 5 6; 7 8 9];
My aim is to index c in a way that I get a 3x3 matrix in which only the values of c are copied over for whose indexes the following conditions are met and the rest are zeros.
a <= 5, b >= 6
Resulting matrix:
result = [0 2 3; 0 0 0; 7 0 9]
I hope I was able to explain my problem.
Given
a = [7 3 4; 5 6 7; 4 8 0];
b = [1 9 8; 2 4 6; 6 1 6];
c = [1 2 3; 4 5 6; 7 8 9];
result = zeros(size(c);
Using logical indexing,
>> d = (a <= 5) & (b >= 6)
d =
0 1 1
0 0 0
1 0 1
>> result(d) = c(d)
result =
0 2 3
0 0 0
7 0 9
Loop throw rows and columns and set the result.
for row=1:size(a,1)
for col=1:size(a,2)
if(a(row,col)> b(row,col))
result(row,col) = 0
else
result(row,col) = c(row,col)
end
end
end
I see people take ==, ~=, >, < between matrixes with a different dimension in parentheses following a matrix to get its entries, like this:
b =
1 4 7
2 5 8
3 6 9
>> b == [1 2 3]
ans =
3×3 logical array
1 0 0
0 0 0
0 0 0
>> b == [1 4 7]
ans =
3×3 logical array
1 1 1
0 0 0
0 0 0
>> b == [1 4 5]
ans =
3×3 logical array
1 1 0
0 0 0
0 0 0
>> b == [1 5 4]
ans =
3×3 logical array
1 0 0
0 1 0
0 0 0
>> a
a =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
>> a(:, b == [1 4 5])
ans =
1 4
1 4
1 4
>> a(:, b == [1 5 4])
ans =
1 5
1 5
1 5
>> b
b =
1 4 7
2 5 8
3 6 9
>> b > [1 3 2]
ans =
3×3 logical array
0 1 1
1 1 1
1 1 1
However, I have no idea why these would work. Any explanation about this usage? (My English is not good to describe the question better, hope anyone could edit this question to make it more understandable? Thanks in advance!)
Since R2016b, MATLAB uses implicit expansion. This means that inputs' singleton dimensions (dimensions of size 1) are repeated to be the same size as other inputs.
For example:
b = [1 4 7
2 5 8
3 6 9]
%% Singleton dimension as rows
b == [x y z]
% is equivalent to
b == repmat([x y z], size(b,1), 1)
% is equivalent to
b == [x y z
x y z
x y z]
%% Singleton dimension as columns
b == [x; y; z]
% is equivalent to
b == repmat([x; y; z], 1, size(b,2))
% is equivalent to
b == [x x x
y y y
z z z]
All 3 of your examples are the "singleton dimension as rows" case, repeating your comparison row vector down and comparing to each row of b. You can easily see that the outputs are as expected.
Implicit expansion can be used in all versions of MATLAB (including pre-R2016b) with the use of bsxfun. This would look like so:
% Since 2016b
b == [1 2 3];
% All versions (#eq is the '==' equals function)
bsxfun(#eq, b, [1 2 3])
I have a matrix A of size nRows x nCols.
I have a nx2 matrix B which contains indices of the matrix A.
I want to get the values of A at the indices given in B.
lets say,
B = [1, 2;
2, 3;
3, 4]
A(1,2) = 1
A(2,3) = 2
A(3,4) = 1
I want to know any Matlab command which gives the following, given A and B (I don't want to use loops):
[1 2 1]
I guess this is what you are looking for:
A(sub2ind(size(A),B(:,1),B(:,2)))
This is what you want:
A = [1,2; 3, 4; 5, 6; 7,8; 9,0]; % this is your N by 2 matrix
B = [1,1; 1,2; 2,1; 3, 1; 4,2]; % these are your indexes
A(sub2ind(size(A), B(:,1), B(:,2)))
A =
1 2
3 4
5 6
7 8
9 0
B =
1 1
1 2
2 1
3 1
4 2
ans =
1
2
3
5
8
So far, i don't get any ideas to understand this error mean. If I have, I think I could solve this problem in my matlab programming.
If anyone could help me to explain what's going on and give some example?
If I is a logical matrix
I =
1 0 1 1 0
and A is an array of the same size,
A =
5 3 8 1 2
then
>> A(I)
ans =
5 8 1
i.e., I works as a mask for the elements in A. You can also use this for assigment:
>> A(I) = 4
A =
4 3 4 4 2
(scalar assignment), or
>> A(I) = [1 NaN 3]
A =
1 3 NaN 3 2
(array assignment). You get the error if you try to do something like
>> A(I) = [ 7 6 5 4 8 7 6 8 7 9 4 3 2]
i.e., A(I) refers to a different number of elements than [7 6 5 4 8 7 6 8 7 9 4 3 2] contains. This is only valid when assigning with a scalar or empty value
A(I) = [] %# valid
A(I) = 4 %# valid
A(I) = [1 2 3] %# valid, numel(A(I)) == numel([1 2 3])
A(I) = [1 2] %# NOT VALID, numel(A(I)) != numel([1 2])
I need some help in converting a 2X2 matrix to a 4X4 matrix in the following manner:
A = [2 6;
8 4]
should become:
B = [2 2 6 6;
2 2 6 6;
8 8 4 4;
8 8 4 4]
How would I do this?
In newer versions of MATLAB (R2015a and later) the easiest way to do this is using the repelem function:
B = repelem(A, 2, 2);
For older versions, a short alternative to the other (largely) indexing-based solutions is to use the functions kron and ones:
>> A = [2 6; 8 4];
>> B = kron(A, ones(2))
B =
2 2 6 6
2 2 6 6
8 8 4 4
8 8 4 4
Can be done even easier than Jason's solution:
B = A([1 1 2 2], :); % replicate the rows
B = B(:, [1 1 2 2]); % replicate the columns
Here's one more solution:
A = [2 6; 8 4];
B = A( ceil( 0.5:0.5:end ), ceil( 0.5:0.5:end ) );
which uses indexing to do everything and doesn't rely on the size or shape of A.
This works:
A = [2 6; 8 4];
[X,Y] = meshgrid(1:2);
[XI,YI] = meshgrid(0.5:0.5:2);
B = interp2(X,Y,A,XI,YI,'nearest');
This is just two-dimensional nearest-neighbor interpolation of A(x,y) from x,y ∈ {1,2} to x,y ∈ {0.5, 1, 1.5, 2}.
Edit: Springboarding off of Jason S and Martijn's solutions, I think this is probably the shortest and clearest solution:
A = [2 6; 8 4];
B = A([1 1 2 2], [1 1 2 2]);
A = [2 6; 8 4];
% arbitrary 2x2 input matrix
B = repmat(A,2,2);
% replicates rows & columns but not in the way you want
B = B([1 3 2 4], :);
% swaps rows 2 and 3
B = B(:, [1 3 2 4]);
% swaps columns 2 and 3, and you're done!
Here's a method based on simple indexing that works for an arbitrary matrix. We want each element to be expanded to an MxN submatrix:
A(repmat(1:end,[M 1]),repmat(1:end,[N 1]))
Example:
>> A=reshape(1:6,[2,3])
A =
1 3 5
2 4 6
>> A(repmat(1:end,[3 1]),repmat(1:end,[4 1]))
ans =
1 1 1 1 3 3 3 3 5 5 5 5
1 1 1 1 3 3 3 3 5 5 5 5
1 1 1 1 3 3 3 3 5 5 5 5
2 2 2 2 4 4 4 4 6 6 6 6
2 2 2 2 4 4 4 4 6 6 6 6
2 2 2 2 4 4 4 4 6 6 6 6
To see how the method works, let's take a closer look at the indexing. We start with a simple row vector of consecutive numbers
>> m=3; 1:m
ans =
1 2 3
Next, we extend it to a matrix, by repeating it M times in the first dimension
>> M=4; I=repmat(1:m,[M 1])
I =
1 2 3
1 2 3
1 2 3
1 2 3
If we use a matrix to index an array, then the matrix elements are used consecutively in the standard Matlab order:
>> I(:)
ans =
1
1
1
1
2
2
2
2
3
3
3
3
Finally, when indexing an array, the 'end' keyword evaluates to the size of the array in the corresponding dimension. As a result, in the example the following are equivalent:
>> A(repmat(1:end,[3 1]),repmat(1:end,[4 1]))
>> A(repmat(1:2,[3 1]),repmat(1:3,[4 1]))
>> A(repmat([1 2],[3 1]),repmat([1 2 3],[4 1]))
>> A([1 2;1 2;1 2],[1 2 3;1 2 3;1 2 3;1 2 3])
>> A([1 1 1 2 2 2],[1 1 1 1 2 2 2 2 3 3 3 3])
There is a Reshape() function that allows you to do this...
For example:
reshape(array, [64, 16])
And you can find a great video tutorial here
Cheers