remove a column from multi-dimensional array on MATLAB - arrays

I have a (n x m x l) array on MATLAB, and I want to remove 'k' columns (on 2nd-dimension). Finally, it may be a (n x (m - k) x l) size.
There is a constraints which is 'n' is fixed. Because MATLAB does not support assign null to array with more than two specific indexes when using colon indexing, I have no idea how can I do this.
Here is my sample code.
channel = 32;
trial = 75;
time = 2000;
data = MyCustomData(...);
disp(data); % ans = [32 75 2000]
for ch = 1:channel
rejected_trials = []
for trial = 1:trial
if(is_rejected_trial(data(ch, trial, :))
rejected_trials(end + 1) = trial;
end
end
data(ch, rejected_trials, :) = []; % This line makes error
end
How can I reject some trials on multi-dimensional array with specific indexes?

Related

How to create matrix in matlab that adds cells horizontally

I want to create a matrix, for example, a 1xn, where n is determined by another input.
For example, I have the following:
Example = [3 5 7 9];
New_matrix = [int_col(Example (1)) int_col(Example (2)) int_col(Example (3)) int_col(Example (4))];
This New_matrix is how I want my outputs.
However, for my actual data input, my Example matrix is 1x47. How can I put this in a for loop so it gives the outputs of 1 to a specified number for all of the length Example? (keeping it horizontal as well)
Help function I used is added here:
% Helper function added as well
function v = int_col(n)
v = zeros(1,n);
for index=1:n
val = randi(n);
while (val == index || any(val == v))
val = randi(n);
if (index == n && (any(v == n) ~= 1))
val = n;
break
end
end
v(index) = val;
if (index == n && val == n)
% v(n) = v(n-1);
% v(n-1) = n;
end
if n == 1
v = 1;
end
end
v = v';
v = (sortrows(v))';
end
Are you trying to reimplement randperm() in int_col()? I'm not sure what the purpose of running sortrows() on each column separately is, but I guess this may be what you wanted:
% Make up vector of column lengths
Example=randi(60,[1 47]);
% Create matrix
New_matrix=nan([max(Example) numel(Example)]);
for i=1:numel(Example)
New_matrix(1:Example(i),i)=randperm(Example(i));
end
% Sort matrix rows from left to right
New_matrix=sortrows(New_matrix);
Please note that all columns in a matrix must have the same number of entries, so you will need to pad shorter columns with some value; a typical choice is NaN, which is treated as a special value by sortrows() and some other functions.
~
If my guess is incorrect and you do mean your code as it currently is, you just need:
New_matrix=[];
for i=1:numel(Example)
New_matrix=[New_matrix 1:Example(i)];
end
Changing the size of New_matrix on every iteration is generally not good practice, but for 47 iterations only this should be fine.

Add arrays that do not have the same length

Problem
Is there a smart way to add arrays/vectors that do not have the same column length, by just adding zeros to columns that are too short? I have additions/subtractions that include multiple variables.
so that:
a=[ 1; 2; 3]; b=[1;5]
a+b=[2; 5; 3]
or:
a-b=[0;-3;3]
instead of:
Error using +
Matrix dimensions must agree.
What I did
b(numel(a),1) = 0;
This works fine, if adding a few variables, but this gets quite annoying while repeating for multiple variables, especially if you don't know which has the longest column. Hence the question if there is an easier fast way for an addition of different column lengths.
Edit
The question really is, if there is a way to automate this for having more than "just a few" variables.
You need to do it more or less manually. For example:
s = [];
s(1,1:numel(a)) = a;
s(2,1:numel(b)) = b; % assigning a row (or column) automatically pads with zeros
% if needed. This works irrespective of which is bigger, a or b
s = sum(s,1); % sum along each column
If you have several variables, it's probably better to put them in a cell array, so you can loop over them:
c = {[1; 2; 3] [1;5] [10 20 30 40]}; % cell array of all "variables"
s = [];
for k = 1:numel(c);
s(k,1:numel(c{k})) = c{k}; % this zero-pads preceding cells' contents if needed
end
s = sum(s,1); % sum along each column
The above may be slow because s is dynamically reallocated. You can preallocate as follows:
c = {[1; 2; 3] [1;5] [10 20 30 40]}; % cell array of all "variables"
m = max(cellfun(#numel, c)); % maximum vector size
s = zeros(numel(c), m); % preallocate and initiallize to zeros
for k = 1:numel(c);
s(k,1:numel(c{k})) = c{k}; % some entries maybe be left as zero
end
s = sum(s,1); % sum along each column
a=[ 1; 2; 3]; b=[1;5];
if numel(b)~=numel(a)
if numel(b)<numel(a) % If b is shorter, extend it
b = [b; zeros(numel(a)-numel(b),1)];
else % If a is shorter, extend it
a = [a; zeros(numel(b)-numel(a),1)];
end
end
a+b
A=[1, 2, 3]; B=[1,5];
[A,zeros(1,length(B)-length(A))]+[B,zeros(1,length(A)-length(B))]
ans =
2 7 3
[A,zeros(1,length(B)-length(A))]-[B,zeros(1,length(A)-length(B))]
ans =
0 -3 3
Stick them in a function and you are done

Elegant way of creating an array full of one number in MATLAB?

I know that to get 10 0's, one can do
A = zeros(10, 1);
To get 10 1's, one can do
A = ones(10, 1);
What about any arbitrary number? Say, I want 10 3's. I have come up with a way of doing it.
A = linspace(3, 3, 10);
Is this satisfactory? Is there a more elegant way of doing this?
Some alternatives:
Using repmat:
A = repmat(3, [5 7]); %// 5x7 matrix filled with the value 3
Using indexing:
A(1:m, 1:n) = x;
Following is a timing comparison between all proposed approaches. As you can see, #Dennis' solutions are the fastest (at least on my system).
Functions:
function y = f1(x,m,n) %// Dennis' "ones"
y = x*ones(m,n);
function y = f2(x,m,n) %// Dennis' "zeros"
y = x+zeros(m,n);
function y = f3(x,m,n) %// Luis' "repmat"
y = repmat(x,[m n]);
function y = f4(x,m,n) %// Luis' "dirty"
y(m,n) = 0;
y(:) = x;
function y = f5(x,m,n) %// Luis' "indexing"
y(1:m,1:n) = x;
function y = f6(x,m,n) %// Divakar's "matrix porod"
y = x*ones(m,1)*ones(1,n);
Benchmarking script for square arrays:
x = 3;
sizes = round(logspace(1,3.7,10)); %// max limited by computer memory
for s = 1:numel(sizes)
n = sizes(s);
m = sizes(s);
time_f1(s) = timeit(#() f1(x,m,n));
time_f2(s) = timeit(#() f2(x,m,n));
time_f3(s) = timeit(#() f3(x,m,n));
time_f4(s) = timeit(#() f4(x,m,n));
time_f5(s) = timeit(#() f5(x,m,n));
time_f6(s) = timeit(#() f6(x,m,n));
end
loglog(sizes, time_f1, 'r.-');
hold on
loglog(sizes, time_f2, 'g.:');
loglog(sizes, time_f3, 'b.-');
loglog(sizes, time_f4, 'm.-');
loglog(sizes, time_f5, 'c.:');
loglog(sizes, time_f6, 'k.:');
xlabel('Array size')
ylabel('Time')
legend('ones', 'zeros', 'repmat', 'dirty', 'indexing', 'matrix prod')
For column arrays: just change the following lines:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = 1;
m = sizes(s);
For row arrays:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = sizes(s);
m = 1;
Results for a dual-core CPU, 2-GB RAM, Windows Vista, Matlab R2010b:
Square arrays;
Column arrays;
Row arrays.
There are two basic ways to do this:
A = ones(10,1)*3
B = zeros(10,1)+3
The first one is most commonly used in examples, yet if I am not mistaken, the second one performs slightly better. All in all it is just a matter of taste.
Of course, if you have an existing matrix, there is another simple way:
C = zeros(10,1)
C(:) = 3;
And for completeness, the repmat solution as suggested by #Luis is also fine.
As an alternative, a matrix multiplication (which is supposed to be pretty fast on MATLAB) based method could be also be suggested for 2D or multidimensional array assignment work.
Thus, assuming m as rows, n as columns and x as the value to be assigned for all elements, the code would be -
y = x*ones(m,1)*ones(1,n);

MATLAB: Run Data Matrix through a loop and add results to data matrix

What I ultimately need is to input a 2-column matrix, run it through a bunch of conditions and have an output of the 2 original columns plus an additional three.
My initial data matrix I split into several arrays according to time (the second column) and continue with applying my conditions on each array individually:
A = arrayfun(#(x) M(M(:, 2) == x, :), unique(M(:,2)), 'uniformoutput', false);
n = numel(A);
k = 0;
for i = 1:n % for each # of arrays
matrix = A{i}; % array i
dat = size(matrix);
length = dat(1,1); % length of i array
adductName = zeros(length, 1); % preallocate columns
actualMass = zeros(length, 1);
adductMass = zeros(length, 1);
%... continued with conditions here's an example of one
for r = 1:length % for the length of array i
mass = matrix(1,r);
M = mass-1;
k=k+1;
if any(M == matrix(:, 1)) % if any M matches rest of column 1 in array
adductName(k) = 'M';
actualMass(k) = M;
adductMass(k) = mass;
else
adductName(k) = 'None';
actualMass(k) = 0;
adductMass(k) = 0;
adductName, actualMass and adductMass are the three additional columns I need added in my output
My question is, how do I recombine all of my arrays, A{i}'s along with my additional three columns into one data matrix to be outputted?
You can either use the [ ] operator or explicit calls to horzcat or vertcat to concatenate matrices in different ways. See the Creating and Concatenating Matrices documentation part for further reference.

Basic MATLAB variable manipulation

I have a dwc = [3001 x 2 double] which more or less is a sin function, I have a for loop finding top values in dwc(:,2). Lets say that there is a top value in dwc(531,2) which way is best way or what is easy to take dwc(531,1) and dwc(531,2) and make an M = [num_of_top_points x 2 double]?
For the following loop, what do I do?
j = 0;
for i = 2:size(dwcL01,1)-1
if dwcL01(i,2) > dwcL01(i-1,2) && dwcL01(i,2) > dwcL01(i+1,2)
j = j+1;
?? = dwcL01(i,:);
end
end
This is how you complete your loop
j = 0;
M = [];
for i = 2:size(dwcL01,1)-1
if dwcL01(i,2) > dwcL01(i-1,2) && dwcL01(i,2) > dwcL01(i+1,2)
j = j+1;
M(j, :) = dwcL01(i, :);
end
end
But you could do this much more efficiently by vectorizing
%//Some example data
x = -4*pi:0.5:4*pi;
y = cos(x);
dwcL01 = [x(:), y(:)]; %// (:) just makes it a column
%// Finding the peaks using diff and sign. Note that I add the first element to the beginning as diff reduces the size by one so this prevents offsetting
F = diff(sign(diff([dwcL01(1,2);dwcL01(:,2)]))) < 0;
M = [dwcL01(F,:)', dwcL01(F,:)'];
plot(x, y, M(:,1), M(:,2), '*r')
How that works is first we find the difference of each element consecutive element pair. Now when the sign changes, that means we've hit a max or min. If the sign change is negative then the gradient went from positive to negative which is a max. So I use diff(sign()) to find the points where the sign changes and then > 0 to create a logical matrix with false everywhere expect for the max. Then I use logical indexing to extract the max.
You could append it to a matrix (let's call it dwcL01_max) - this isn't the fastest way because the matrix size changes each loop but it works:
dwcL01_max = [dwcL01_max dwcL01(i,:)];
The other option would be to use the builtin findpeaks (from the signal proc toolbox)
[~, dwcL01_peaks] = findpeaks(dwcL01(:,2));
dwcL01_max = dwcL01(dwcL01_peaks, :);

Resources