I have this line of code in MATLAB, which sets these vectors:
x = [2 12 3 8 1 9 2; -3 -2 -1 0 1 2 3]
x =
2 12 3 8 1 9 2
-3 -2 -1 0 1 2 3
Considering the first row as points in y-plane and second row as x-axis in MATLAB plot
Now what line of code in MATLAB will take the maximum number in the first row and set at the middle(0) point in x-axis which will make it look like this
x =
9 2 2 12 3 8 1
-3 -2 -1 0 1 2 3
Please any idea is appreciated, I don't know how best to ask this question, I'm actually trying to edit a plot in MATLAB.
Code:
x = [2 12 3 8 1 9 2; -3 -2 -1 0 1 2 3];
[~,idx] = max(x(1,:));
x(1,:) = circshift(x(1,:),[0 (length(x)+1)/2-idx]);
Output:
x =
9 2 2 12 3 8 1
-3 -2 -1 0 1 2 3
Related
This question already has answers here:
How to create a symmetric matrix where each row/column is a subset of a known vector [duplicate]
(2 answers)
How do I generate the following matrix and vector from the given input data in MATLAB?
(1 answer)
Closed 5 years ago.
I have a vectorb with 30 entries.
I want to avoid using a for loop to construct a matrix like this:
where b_i is the i-th entry of the vector b.
For example, define the vector
b = [2 6 -7 3 1 -4 -1 1 11 8 -4 9 2 0 2 -1 0 4 4 4 2 -4 2 5 1 3 2 -1 1 -2]
where I tried by using for loop is:
A = zeros(5,5);
for i = 1:5
A(i) = b(i+5);
A(i+5) = b(i+6);
A(i+10) = b(i+7);
A(i+15) = b(i+8);
A(i+20) = b(i+9);
end
The result is
Is there a faster and more general method to generate this matrix?
You can use toeplitz:
A=fliplr(toeplitz(b(10:14),b(10:-1:6))
A =
-4 -1 1 11 8
-1 1 11 8 -4
1 11 8 -4 9
11 8 -4 9 2
8 -4 9 2 0
By the way, the indices here are 6 to 14 as in your example, and not 7 to 15 as in the picture. You can change it to your preferred purpose.
Your instinct is to avoid for loops. This is a good intuition to develop as a MATLAB programmer, but it's not always the quickest option. As can be seen in my answer to a very similar question, a for loop may be the quickest way to generate this type of matrix.
Possibly the shortest method to write would use hankel
A = b(hankel(7:11, 11:15));
Output:
>> ans =
-1 1 11 8 -4
1 11 8 -4 9
11 8 -4 9 2
8 -4 9 2 0
-4 9 2 0 2
Equivalent result (but quicker processing as seen in the previously linked answer)
A = hankel(b(7:11), b(11:15));
As Adiel said, there is a difference between the indices you showed in the image of the matrix and the indices you used to create your example. This uses the former.
Not as nice as using toeplitz, but a bit clearer to see what's going on:
b = [2 6 -7 3 1 -4 -1 1 11 8 -4 9 2 0 2 -1 0 4 4 4 2 -4 2 5 1 3 2 -1 1 -2];
n = 5; % window size
% StartIdx = 4; % Starting index of your window
AddVec = repelem(1:n,5)+StartIdx; % create addition vector
IdxVec = repmat(1:n,1,n); % Initialise index vector
IdxVec = AddVec+IdxVec; % add to let the window "slide"
c = b(IdxVec); % create a new vector
d = reshape(c,n,[]) % Reshape to get the desired matrix
d =
6 -7 3 1 -4
-7 3 1 -4 -1
3 1 -4 -1 1
1 -4 -1 1 11
-4 -1 1 11 8
Note that I didn't use a starting index in my run of the matrix. Adjust that parameter according to your needs.
Say I have the following matrix:
A(:,1) = [-5 -5 5 5 -5 -5 -5 -5 5 5 5 5]';
A(:,2) = [8 7 3 6 5 9 8 7 9 4 3 2 ]';
I'd like to split it into 4 groups based on the signs in the first column (i.e. everything prior to a sign flip is one group):
1) -5 -5
2) 5 5
3) -5 -5 -5 -5
4) 5 5 5 5
and the corresponding grouping in the second column would then be:
1) 8 7
2) 3 6
3) 5 9 8 7
4) 9 4 3 2
My intuition is to use
diff(A(:,1)) ~= 0
as the first step, but I am unsure how to continue from there. Any help would be appreciated, thanks!
You can use accumarray to create this cell array for you. We first need to assign a unique value to each "group" of consecutive numbers which share a sign. We can then use accumarray to place all elements in a given group into an element of a cell array.
A = cat(1, [-5 -5 5 5 -5 -5 -5 -5 5 5 5 5], [8 7 3 6 5 9 8 7 9 4 3 2 ]).';
% Compute the sign of each element: -1 for negative, 1 for positive
% Repeat first element for diff
S = sign(A([1 1:end],1));
% -1 -1 -1 1 1 -1 -1 -1 -1 1 1 1 1
% Compute element-by-element differences
D = diff(S);
% 0 0 2 0 -2 0 0 0 2 0 0 0
% Convert to a logical matrix which will make any non-zero 1 and any zero stays 0
L = logical(D);
% 0 0 1 0 1 0 0 0 1 0 0 0
% Take the cumulative sum (and add 1) to give each group of elements a unique number
subs = cumsum(L) + 1;
% 1 1 2 2 3 3 3 3 4 4 4 4
% Use this as the first input to accumarray and perform a given action on all elements in
% A(:,2) which share these values. Our action will be to convert to a cell array
result = accumarray(subs, A(:,2), [], #(x){x});
% result{1} =
% 8 7
%
% result{2} =
% 3 6
%
% result{3} =
% 5 9 8 7
%
% result{4} =
% 9 4 3 2
If we really want to reduce it so a single line we could do this.
accumarray(1 + cumsum(logical(diff(sign(A([1 1:end],1))))), A(:,2), [], #(x){x})
Use:
groupsSizes= diff([0;find(conv(A(:,1),[1,-1],'same')~=0)]);
firstGroup = mat2cell(A(:,1),groupsSizes,1);
secondGroup = mat2cell(A(:,2),groupsSizes,1);
Here's another way:
result = mat2cell(A(:), diff([0; find([diff(sign(A(:))); true])]));
This uses mat2cell to split A into pieces and put each into a cell. The length of the pieces is computed using sign to detect the sign and then diff and find to obtain the run lengths.
I have random matrix with arbitrary dimensions and I want to assign a color for each value (randomly or not) and plot the matrix with numbers like,
So far I've done this,
m = 12;
n = 8;
A = randi(5,[m n]);
Arot = flipud(A);
pcolor(Arot);figure(gcf);
for i = 1 : n -1
for j = 1 : m -1
text(i + .5 , j + .5 ,num2str(Arot(j,i)),'FontSize',18);
end
end
which gives me this,
for
A =
4 4 4 1 2 1 4 2
5 2 2 3 2 1 1 2
1 2 1 4 1 2 5 5
1 3 5 3 1 4 1 3
3 4 4 4 3 3 3 4
2 5 2 2 1 1 2 4
1 3 1 3 5 5 2 4
5 1 2 4 1 4 1 2
2 4 5 5 1 3 5 2
4 2 2 3 4 3 3 4
3 5 3 2 4 3 3 1
1 4 5 3 2 4 3 5
but as you can see I've lost first row and last column of A.
Actually the problem starts bu using pcolor, which gives an (m-1)x(n-1) plot for mxn input.
Any suggestions?
Thanks,
Using imagesc instead of pcolor solves the problem. It also brings some other benefits:
Avoids the need for flipud;
The coordinates of the text objects become integer values;
Axes are automatically set to "matrix" mode, with the origin in the upper right corner.
Code:
m = 8;
n = 6;
A = randi(5,[m n]);
imagesc(A);
for ii = 1:n
for jj = 1:m
text(ii, jj, num2str(A(jj,ii)), 'FontSize', 18);
end
end
For
A =
4 5 4 2 4 4
5 4 3 4 4 2
5 4 1 1 1 3
4 3 5 2 5 4
1 2 2 2 5 3
1 5 2 5 1 3
4 3 1 3 3 1
3 1 2 4 2 3
this produces
I just padded the matrix prior to pcolor and I think it's the effect you wanted. The reason it works comes from the help doc for pcolor, which states that
In the default shading mode, 'faceted', each cell has a constant color
and the last row and column of C are not used.
m = 12;
n = 8;
A = randi(5,[m n]);
Arot = flipud(A);
Arot = [ Arot; Arot(end,:) ];
Arot = [ Arot, Arot(:,end) ];
pcolor(Arot);figure(gcf);
for i = 1 : n
for j = 1 : m
text(i + .5 , j + .5 ,num2str(Arot(j,i)),'FontSize',18);
end
end
If I have an arbitrary n*m matrix called data and I would like to take differences of the matrix using gradually bigger steps.
The first case would have a first column equal to data(:,2)-data(:,1), the next column would be data(:,3)-data(:,2) and so on. This can be done with the following function.
data = diff(data,1,2)
Similarly I would also like to take differences based of every second column, so that the first entry would be data(:,3)-data(:,1) and the next data(:,5)-data(:,3) and so on.
This can't be done with diff, but is there any other function or method that can do it without resorting to looping?
I need to do the same thing for every n value up to 50.
Use column indexing to select the "right" columns and then use your favourite diff -
A = randi(9,4,9) %// Input array
stepsize = 2; %// Edit this for a different stepsize
out = diff(A(:,1:stepsize:end),1,2)
Output -
A =
8 9 9 8 3 2 6 8 7
2 5 5 7 5 3 9 6 3
2 7 7 2 4 1 2 4 1
6 2 1 5 4 9 9 3 7
out =
1 -6 3 1
3 0 4 -6
5 -3 -2 -1
-5 3 5 -2
I just wrote a simple wrapper function for the purpose.
function [ out ] = diffhigh( matrix, offset )
matrix_1 = matrix(:,(offset+1):size(matrix,1));
matrix_2 = matrix(:, 1:(size(matrix,1)-offset));
out = matrix_1 - matrix_2;
end
>> a
a =
3 5 1 2 4
1 2 3 4 5
1 4 5 3 2
1 2 4 3 5
2 1 5 3 4
>> diffhigh(a, 2)
ans =
-2 -3 3
2 2 2
4 -1 -3
3 1 1
3 2 -1
>> diffhigh(a, 3)
ans =
-1 -1
3 3
2 -2
2 3
1 3
I want to centre a matrix to its mean,
A[i][j] = A[i][j]-mean(A,j)
So I subtract from each point the mean of the according column.
I could not find a function to centre my data, and it is not very straightforward to create my own
>> A=[1 4 7;2 5 8;3 6 9]
A =
1 4 7
2 5 8
3 6 9
>> A-repmat(mean(A),size(A,1),1)
ans =
-1 -1 -1
0 0 0
1 1 1
A = bsxfun(#minus,A,mean(A));
for example:
A = magic(5);
A = bsxfun(#minus, A, mean(A))
A =
4 11 -12 -5 2
10 -8 -6 1 3
-9 -7 0 7 9
-3 -1 6 8 -10
-2 5 12 -11 -4