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.
Related
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?
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
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.
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, :);
Here is the C# code I am trying to translate:
public bool equals(Matrix matrix, int precision)
{
if (precision < 0)
{
throw new MatrixError("Precision can't be a negative number.");
}
double test = Math.Pow(10.0, precision);
if (double.IsInfinity(test) || (test > long.MaxValue))
{
throw new MatrixError("Precision of " + precision
+ " decimal places is not supported.");
}
precision = (int)Math.Pow(10, precision);
for (int r = 0; r < this.Rows; r++)
{
for (int c = 0; c < this.Cols; c++)
{
if ((long)(this[r, c] * precision) != (long)(matrix[r, c] * precision))
{
return false;
}
}
}
return true;
}
Here is what I have so far:
type Matrix(sourceMatrix:double[,]) =
let rows = sourceMatrix.GetUpperBound(0) + 1
let cols = sourceMatrix.GetUpperBound(1) + 1
let matrix = Array2D.zeroCreate<double> rows cols
do
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
matrix.[i,j] <- sourceMatrix.[i,j]
///The number of Rows in this Matrix.
member this.Rows = rows
///The number of Columns in this Matrix.
member this.Cols = cols
member this.Equals(matrix:Matrix, precision:int) =
if(precision < 0) then raise (new ArgumentOutOfRangeException("Precision can't be a negative number."))
let (test:double) = Math.Pow(10.0, double(precision))
if(System.Double.IsInfinity(test) || (test > double(System.Int32.MaxValue))) then raise (new ArgumentOutOfRangeException("Precision of " + precision.ToString() + " decimal places is not supported."))
let precision = int(Math.Pow(10.0, double(precision)))
As you can see what I have written so far is loaded with type casts which probably means my code is not written the way it should be. The unfinished part needs the method to return on the first element which returns false when evaluated to a certain precision. I'm sure there must be some elegant F# code to achieve this and clearly I am nowhere near it. I was trying to figure out if the Array2D class had some method on it that would allow me to do this, but I wasn't able to find it if there is. I am aware of the PowerPack Matrix class and will use it eventually, but for now I'm trying to learn F# by translating C# code I understand into F#. Easier said than done apparently. :) I believe I've added all the relevant F# code in the type I'm creating. Let me know if I'm missing something.
An elegant and high-level way to write this that probably won't be extremely efficient is to use lazy sequence expressions:
seq { for r in 0 .. this.Rows - 1 do
for c in 0 .. this.Cols - 1 do
if <your condition goes here> then
yield false}
|> Seq.forall id
The idea is that the sequence will generate false as soon as the first element in the matrix matches the condition. Then the Seq.forall function immediately returns false (and stops iterating over the sequence).
In practice, you'll probably need to implement this using recursive function to make it efficient. This is not particularly nice (because breaking out of loops cannot be done in F#), but you shouldn't need code like this too often:
let rec loopRows r =
let rec loopCols c =
if c = this.Cols then true
elif <your condition goes here> then false
else loopCols (c + 1)
if r = this.Rows then true // Processed all rows
elif not (loopCols 0) then false // Nonequal element in this row
else loopRows (r + 1) // Continue looping
loopRows 0
Here's a liberal translation of your code:
type Matrix(sourceMatrix) =
let rows = Array2D.length1 sourceMatrix
let cols = Array2D.length2 sourceMatrix
let matrix = Array2D.copy sourceMatrix
///The number of Rows in this Matrix.
member this.Rows = rows
///The number of Columns in this Matrix.
member this.Cols = cols
///Retrieve data from this Matrix
member this.Item(x,y) = matrix.[x,y]
member this.Equals(matrix:Matrix, precision) =
if precision < 0 then failwith "Precision can't be a negative number."
let precision = 10.0 ** double(precision)
if Double.IsInfinity(precision) then failwith ("Precision of " + string(precision) + " decimal places is not supported.")
seq {
for r in 0 .. rows - 1 do
for c in 0 .. cols - 1 do
if floor(matrix.[r, c] * precision) <>
floor(this.[r, c] * precision) then
yield false
} |> Seq.forall id
Notice how I changed the array method calls to Array2D function calls, which cleaned things up a bit. Then I added an indexer (this.Item) so that you can actually read the data from the matrix.
You will note that I changed the use of conversion to integers with calls to floor, which eliminates much of the need to convert between ints and floats.
The comparison is done inside a lazy sequence as Thomas suggested.