I have an array (2000x2) with two variables and want to calculate the mean of column 2 at intervals determined by column 1. How can i do this?
speed=(:,1); %values range from 0-100 cm/s
press=(:,2);
I want to calculate mean pressure at at 5 cm/s intervals of speed. So that I get 20 values for pressure that correspond to 20 intervals of speed.
Should be simple, but I'm still a beginner in Matlab.
The accumarray function does just that:
data = [0 20 33 44 22 56 25 47 81 90; 3 5 4 3 2 4 5 5 6 0].';
speed = data(:,1);
press = data(:,2);
sz = 5; % interval size
fill = NaN; % fill value in the result, for empty groups
group = floor(speed/sz)+1; % compute index of group for each value
result = accumarray(group, press, [], #mean, NaN); % compute mean of each group
I believe the answer to this is simple but my brain will not function.
Say I have a m x n matrix which is of type double & lets call it A. I also have a matrix B, which is m x n and is all NaN's.
I then want to find out which numbers are say equal to some number, let say 100. I can do the following,
A_index = A == 100;
So I now have a logical array, A_index. This is all fine.
My question is how do I select the elements from A where A_index is true into matrix B?
Some made up matrices
A= [ 50 100 75 90 100; 0 50 60 30 10; 100 25 80 250 100; 5 100 0 100 90];
A_index = A == 100;
B= zeros(4,5) * NaN;
Something like:
A= [ 50 100 75 90 100; 0 50 60 30 10; 100 25 80 250 100; 5 100 0 100 90];
A_index = A == 100;
B= zeros(4,5) * NaN;
B(A_index) = 100
This way you will get 100 in the entries of B where A is equal to 100
See the section on logical indexing in the MATLAB docs
a= [1 2 13 20 10 20 12 1 13 14]
b= [1:10:100]
plot(a,b)
I want to find the maximum('a') from the plot and then take the corresponding point let say 'a3,b3' and store it some where else and remove it from the plot. then I want to subtract 'a3' from every point left in 'a' and plot the graph. and I need to do this again till it reaches an thresh hold point.
This seems like an odd request but if I understand correctly.
%Input data
a = [1 2 13 20 10 20 12 1 13 14];
b = [1:10:100];
%Some threshold (which you didn't specify
lengthA = 4;
%Initialize storage vector
aPrime = a;
bPrime = b;
%While vector
while (length(aPrime) >= lengthA)
%New figure
figure;
%Plot vector
plot(aPrime, bPrime)
%Find index and max value in a'
[aMax, index] = max(aPrime);
%Find max value in b'
bMax = bPrime(index);
%Remove max value from vector and subtract off max value
aPrime = aPrime([1:index - 1, index + 1:end]) - aMax;
bPrime = bPrime([1:index - 1, index + 1:end]) - bMax;
end
I hope someone can help me.
Lets say I have the following two vectors
t = [1 2 3 4 5];
m = [10 8 6 4 2];
plot(t,m)
And I want to find the slope of the linear fit (1. degree)
so I write:
polyfit(t,m,1)
I then obtain the following answer:
ans =
-2.0000 12.0000
Meaning that y = -2x + 12
How do I re-calculate the coefficient to a percentage slope?
The reason I am interested in this is that I want to discard all data that has a slope < 80% (and proceed with data with slope coefficients between 80% and 100%).
Assuming that you define percentage slope by the formula given in #2 of the Nopmenclature section on the Wikipedia Grade page, 100 * dy / dx, your percentage slope is just the coefficient of x^1, multiplied by 100. You can do a test to check for slopes < 80% as follows:
t = [1 2 3 4 5];
m = [10 8 6 4 2];
p = polyfit(t,m,1);
g = p(1) * 100;
if g > 80 && g < 100
% Do what you need to do...
end
I have an NxM matrix in MATLAB that I would like to reorder in similar fashion to the way JPEG reorders its subblock pixels:
(image from Wikipedia)
I would like the algorithm to be generic such that I can pass in a 2D matrix with any dimensions. I am a C++ programmer by trade and am very tempted to write an old school loop to accomplish this, but I suspect there is a better way to do it in MATLAB.
I'd be rather want an algorithm that worked on an NxN matrix and go from there.
Example:
1 2 3
4 5 6 --> 1 2 4 7 5 3 6 8 9
7 8 9
Consider the code:
M = randi(100, [3 4]); %# input matrix
ind = reshape(1:numel(M), size(M)); %# indices of elements
ind = fliplr( spdiags( fliplr(ind) ) ); %# get the anti-diagonals
ind(:,1:2:end) = flipud( ind(:,1:2:end) ); %# reverse order of odd columns
ind(ind==0) = []; %# keep non-zero indices
M(ind) %# get elements in zigzag order
An example with a 4x4 matrix:
» M
M =
17 35 26 96
12 59 51 55
50 23 70 14
96 76 90 15
» M(ind)
ans =
17 35 12 50 59 26 96 51 23 96 76 70 55 14 90 15
and an example with a non-square matrix:
M =
69 9 16 100
75 23 83 8
46 92 54 45
ans =
69 9 75 46 23 16 100 83 92 54 8 45
This approach is pretty fast:
X = randn(500,2000); %// example input matrix
[r, c] = size(X);
M = bsxfun(#plus, (1:r).', 0:c-1);
M = M + bsxfun(#times, (1:r).'/(r+c), (-1).^M);
[~, ind] = sort(M(:));
y = X(ind).'; %'// output row vector
Benchmarking
The following code compares running time with that of Amro's excellent answer, using timeit. It tests different combinations of matrix size (number of entries) and matrix shape (number of rows to number of columns ratio).
%// Amro's approach
function y = zigzag_Amro(M)
ind = reshape(1:numel(M), size(M));
ind = fliplr( spdiags( fliplr(ind) ) );
ind(:,1:2:end) = flipud( ind(:,1:2:end) );
ind(ind==0) = [];
y = M(ind);
%// Luis' approach
function y = zigzag_Luis(X)
[r, c] = size(X);
M = bsxfun(#plus, (1:r).', 0:c-1);
M = M + bsxfun(#times, (1:r).'/(r+c), (-1).^M);
[~, ind] = sort(M(:));
y = X(ind).';
%// Benchmarking code:
S = [10 30 100 300 1000 3000]; %// reference to generate matrix size
f = [1 1]; %// number of cols is S*f(1); number of rows is S*f(2)
%// f = [0.5 2]; %// plotted with '--'
%// f = [2 0.5]; %// plotted with ':'
t_Amro = NaN(size(S));
t_Luis = NaN(size(S));
for n = 1:numel(S)
X = rand(f(1)*S(n), f(2)*S(n));
f_Amro = #() zigzag_Amro(X);
f_Luis = #() zigzag_Luis(X);
t_Amro(n) = timeit(f_Amro);
t_Luis(n) = timeit(f_Luis);
end
loglog(S.^2*prod(f), t_Amro, '.b-');
hold on
loglog(S.^2*prod(f), t_Luis, '.r-');
xlabel('number of matrix entries')
ylabel('time')
The figure below has been obtained with Matlab R2014b on Windows 7 64 bits. Results in R2010b are very similar. It is seen that the new approach reduces running time by a factor between 2.5 (for small matrices) and 1.4 (for large matrices). Results are seen to be almost insensitive to matrix shape, given a total number of entries.
Here's a non-loop solution zig_zag.m. It looks ugly but it works!:
function [M,index] = zig_zag(M)
[r,c] = size(M);
checker = rem(hankel(1:r,r-1+(1:c)),2);
[rEven,cEven] = find(checker);
[cOdd,rOdd] = find(~checker.'); %'#
rTotal = [rEven; rOdd];
cTotal = [cEven; cOdd];
[junk,sortIndex] = sort(rTotal+cTotal);
rSort = rTotal(sortIndex);
cSort = cTotal(sortIndex);
index = sub2ind([r c],rSort,cSort);
M = M(index);
end
And a test matrix:
>> M = [magic(4) zeros(4,1)];
M =
16 2 3 13 0
5 11 10 8 0
9 7 6 12 0
4 14 15 1 0
>> newM = zig_zag(M) %# Zig-zag sampled elements
newM =
16
2
5
9
11
3
13
10
7
4
14
6
8
0
0
12
15
1
0
0
Here's a way how to do this. Basically, your array is a hankel matrix plus vectors of 1:m, where m is the number of elements in each diagonal. Maybe someone else has a neat idea on how to create the diagonal arrays that have to be added to the flipped hankel array without a loop.
I think this should be generalizeable to a non-square array.
% for a 3x3 array
n=3;
numElementsPerDiagonal = [1:n,n-1:-1:1];
hadaRC = cumsum([0,numElementsPerDiagonal(1:end-1)]);
array2add = fliplr(hankel(hadaRC(1:n),hadaRC(end-n+1:n)));
% loop through the hankel array and add numbers counting either up or down
% if they are even or odd
for d = 1:(2*n-1)
if floor(d/2)==d/2
% even, count down
array2add = array2add + diag(1:numElementsPerDiagonal(d),d-n);
else
% odd, count up
array2add = array2add + diag(numElementsPerDiagonal(d):-1:1,d-n);
end
end
% now flip to get the result
indexMatrix = fliplr(array2add)
result =
1 2 6
3 5 7
4 8 9
Afterward, you just call reshape(image(indexMatrix),[],1) to get the vector of reordered elements.
EDIT
Ok, from your comment it looks like you need to use sort like Marc suggested.
indexMatrixT = indexMatrix'; % ' SO formatting
[dummy,sortedIdx] = sort(indexMatrixT(:));
sortedIdx =
1 2 4 7 5 3 6 8 9
Note that you'd need to transpose your input matrix first before you index, because Matlab counts first down, then right.
Assuming X to be the input 2D matrix and that is square or landscape-shaped, this seems to be pretty efficient -
[m,n] = size(X);
nlim = m*n;
n = n+mod(n-m,2);
mask = bsxfun(#le,[1:m]',[n:-1:1]);
start_vec = m:m-1:m*(m-1)+1;
a = bsxfun(#plus,start_vec',[0:n-1]*m);
offset_startcol = 2- mod(m+1,2);
[~,idx] = min(mask,[],1);
idx = idx - 1;
idx(idx==0) = m;
end_ind = a([0:n-1]*m + idx);
offsets = a(1,offset_startcol:2:end) + end_ind(offset_startcol:2:end);
a(:,offset_startcol:2:end) = bsxfun(#minus,offsets,a(:,offset_startcol:2:end));
out = a(mask);
out2 = m*n+1 - out(end:-1:1+m*(n-m+1));
result = X([out2 ; out(out<=nlim)]);
Quick runtime tests against Luis's approach -
Datasize: 500 x 2000
------------------------------------- With Proposed Approach
Elapsed time is 0.037145 seconds.
------------------------------------- With Luis Approach
Elapsed time is 0.045900 seconds.
Datasize: 5000 x 20000
------------------------------------- With Proposed Approach
Elapsed time is 3.947325 seconds.
------------------------------------- With Luis Approach
Elapsed time is 6.370463 seconds.
Let's assume for a moment that you have a 2-D matrix that's the same size as your image specifying the correct index. Call this array idx; then the matlab commands to reorder your image would be
[~,I] = sort (idx(:)); %sort the 1D indices of the image into ascending order according to idx
reorderedim = im(I);
I don't see an obvious solution to generate idx without using for loops or recursion, but I'll think some more.