In MATLAB, i was faced with a incomprehensible syntax.
for i = [1:n-1,n+1:N]
Z{i} = U{i}(:,r);
end
if you knows exactly, please let me know.
(if you show some example(e.g. when n=1, N=3), i can understand your explain easily.)
This syntax basically means:
for i = [1:n-1,n+1:N]
This just means that i will sequentially take the values defined in the array:
1 till n-1 increasing by 1 and after it will continue from n+1 till N. It will skip n in other words.
Z{i} = U{i}(:,r);
{ represent cells so the ith cell of Z (imagine Z and U as cell arrays) will be assigned the content of ith cell of U from which it will keep though only the r-th column (I guess its a matrix of some kind).
Related
I have a problem using matrix multiplication in Matlab.
I have a 8x4 matrix called A and a 4x1 vector called B. Looking at matrix A, the fourth row of has the values
A(4,:) = (-19.723654104483987, -73.609679228848705, 73.609679228848705, 19.723654104483987)
and the vector B has the values
B = (101325, 101325, 101325, 101325)'.
It appears to me that these two, when multiplied, would cancel eachother out. However, when I use A*B = ans, the fourth row of ans has a value as shown below.
ans(4) = 4.656612873077393e-10
I find this strange since I tried to check if the elements of A(4,:) and they really should cancel out since
(A(4,1) == -A(4,4)) = 1
(A(4,2) == -A(4,3)) = 1
and
(B(1) == B(2)) = 1
(B(1) == B(3)) = 1
(B(1) == B(4)) = 1
I was thinking that it might have something to do with the machine epsilon of Matlab, but the answer is larger than e-16.
Another thing I find strange is that when I use A(4,:)*B it returns 0. Why does a value appear on the forth row when using full scale matrix multiplication?
If anyone has an idea why this doesn't return zero, I would be grateful!
You are computing an expression
((-a+(-b))+b)+a, a,b > 0
Floating point operations are not commutative, the truncation error committed by the first addition of -a and -b is not undone by the second addition of b, so the third addition of a will not land at zero, but will reflect the truncation error of the first sum. So it is not surprising that you get a residual error of size (a+b)*mu, mu being the machine constant, about 2e-16. As your a+b is about 1e+7, this conforms with the actual result you got.
See also the many resources provided in Is floating point math broken?
I am trying to remove rows from a matrix based on a condition. I have a 371000x5 double matrix, and a 371000x1 vector of dummies (1 and 0). I want to remove each row from the original matrix, where the value of the vector of dummies is 1.
I have tried the following, but it is taking very long:
for i = 1:size(matrix_num,1)
if missing_matrix(i,1) >=0
matrix_num(i,:) = [];
end
end
My Matlab has been busy for over 30 minutes now, so I am not even sure if the code is right. Is there a more efficient way to do this?
Additionally, I have to do the same action on a cell matrix (categorical data). Should I expect any huge difference from the numerical matrix?
The programmatic way of doing this is:
new_matrix = old_matrix(missing_vector==1,:)
for keeping lines with missing_vector 1
new_matrix = old_matrix(missing_vector==0,:)
for removing lines with missing_vector 1
For educational values, if you want the loop to work, don't do that row by row. Your solution causes the matrix to be copied and re-allocated on every row removed.
So, you would be better off if you calculate the resulting matrix size in advance:
new_matrix = zeros(sum(missing_vector), 5)
and then your iteration would work:
index_new=1
for index_old = 1:size(old_matrix,1)
if missing_vector(index_old) ==0
new_matrix(index_new,:) = old_matrix(index_old,:);
end
end
Try compact MATLAB code
matrix_num(missing_matrix>=0,:)=[]
Note : You must make a vector for missing_matrix variable. If this variable is matrix, you need other form of code .
As I know, you can use it in cell array too.
I need to create a function that has the input argument n, a integer , n>1 , and an output argument v, which is a column vector of length n containing all the positive integers smaller than or equal to n, arranged in such a way that no element of the vector equals its own index.
I know how to define the function
This is what I tried so far but it doesn't work
function[v]=int_col(n)
[1,n] = size(n);
k=1:n;
v=n(1:n);
v=k'
end
Let's take a look at what you have:
[1,n] = size(n);
This line doesn't make a lot of sense: n is an integer, which means that size(n) will give you [1,1], you don't need that. (Also an expression like [1,n] can't be on the left hand side of an assignment.) Drop that line. It's useless.
k=1:n;
That line is pretty good, k is now a row vector of size n containing the integers from 1 to n.
v=n(1:n);
Doesn't make sense. n isn't a vector (or you can say it's a 1x1 vector) either way, indexing into it (that's what the parentheses do) doesn't make sense. Drop that line too.
v=k'
That's also a nice line. It makes a column vector v out of your row vector k. The only thing that this doesn't satisfy is the "arranged in such a way that no element of the vector equals its own index" part, since right now every element equals its own index. So now you need to find a way to either shift those elements or shuffle them around in some way that satisfies this condition and you'd be done.
Let's give a working solution. You should really look into it and see how this thing works. It's important to solve the problem in smaller steps and to know what the code is doing.
function [v] = int_col(n)
if n <= 1
error('argument must be >1')
end
v = 1:n; % generate a row-vector of 1 to n
v = v'; % make it a column vector
v = circshift(v,1); % shift all elements by 1
end
This is the result:
>> int_col(5)
ans =
5
1
2
3
4
Instead of using circshift you can do the following as well:
v = [v(end);v(1:end-1)];
I have a 1x10 ( say 10 because it is actually 262144, but for the purpose of my question, 10 is enough) cell array called x. Each cell is an array of 0 to 4 real values.
I'd like to run an if condition based on the number of element in each cell, WITHOUT using a for loop (as I said, it is actually 262144 cell long, so a for loop might be a bit heavy).
for loop exemple to show what I want to do :
for i = 1:10
if numel(x{i}) > 2
h(i) = 0;
else
h(i) = 1;
end
end
And then I'll want to run a while loop independantly on each cell, incrementing h by 1 until it reaches the value of the lenght of the cell.
len = cellfun(#numel,x)
while h < len
h = h+1;
%code that does thing on each cell still in the while loop
end
I've never seen anything like that online even though I've looked quite thoroughly. If anyone can give me a global indication on how to work independantly on separate cells without using a for loop (which is the core of my problem), I'd be great!
EDIT : Knowing how to operate on value X of all cells would be great too. E.g:
k = x{:}(1) < x{:}(2)
This doesn't work, but I don't know why and I don't what would. Trying to compare all first values with all second values.
For your first problem, you can easily use a combination of cellfun and logical indexing to generate h:
h = cellfun(#numel, x) <= 2;
The <= 2 bit will return a 1 if a value is, well, less than or equal to 2, and 0 otherwise.
Note that for and while loops really aren't slow, so maybe what you have written is "good enough".
EDIT: With regards to your new, edited question: naively this can't be done unless you can guarantee that the length of each array inside each cell is the same. I will assume that it is.
If that's the case, you can simply call cell2mat to convert the cell array to a matrix, then directly compare the two columns:
A = cell2mat(x);
k = A(:,1) < A(:,2);
If the lengths are all different, you can fill them with zeros or nan or something to make them the same length.
I have a set of data that is <106x25 double> but this is inside a struct and I want to extract the data into a matrix. I figured a simple FOR loop would accomplish this but I have hit a road block quite quickly in my MATLAB knowledge.
This is the only piece of code I have, but I just don't know enough about MATLAB to get this simple bit of code working:
>> x = zeros(106,25); for i = 1:106, x(i,:) = [s(i).surveydata]; end
??? Subscripted assignment dimension mismatch.
's' is a very very large file (in excess of 800MB), it is a <1 x 106 struct>. Suffice it to say, I just need to access a small portion of this which is s.surveydata where most rows are a <1 x 25 double> (a row vector IIRC) and some of them are empty and solely return a [].
s.surveydata obviously returns the results for all of the surveydata contained where s(106).surveydata would return the result for the last row. I therefore need to grab s(1:106).surveydata and put it into a matrix x. Is creating the matrix first by using x = zeros(106,25) incorrect in this situation?
Cheers and thanks for your time!
Ryan
The easiest, cleanest, and fastest way to write all the survey data into an array is to directly catenate it, using CAT:
x = cat(1,s.surveydata);
EDIT: note that if any surveydata is empty, x will have fewer rows than s has elements. If you need x to have the same amount of rows as s has elements, you can do the following:
%# find which entries in s have data
%# note that for the x above, hasData(k) contains the
%# element number in s that the k-th row of x came from
hasData = find(arrayfun(#(x)~isempty(x.surveydata),s));
%# initialize x to NaN, so as to not confuse the
%# real data with missing data entries. The call
%# to hasData when indexing makes this robust to an
%# empty first entry in s
x = NaN(length(s),length(s(hasData(1)).surveydata);
%# fill in only the rows of x that contain data
x(hasData,:) = cat(1,s(hasData).surveydata);
No, creating an array of zeroes is not incorrect. In fact it's a good idea. You don't have to declare variables in Matlab before using them, but for loops, pre-allocating has speed benefits.
x = zeros(size(s), size(s(1)));
for i = 1:106
if ~isempty(s(i).surveydata)
x(i, :) = s(i).surveydata;
end
end
Should accomplish what you want.
EDIT: Since OP indicated that some rows are empty, I accounted for that like he said.
what about this?
what s is?
if s(i).surveydata is scalar:
x = zeros(106,25);
for i = 1:106
x(i,1) = [s(i).surveydata];
end
I am guessing that is what you want tough it is not clear at all :
if s(i).surveydata is row vector:
x = zeros(106,25);
for i = 1:106
x(i,:) = [s(i).surveydata];
end
if s(i).surveydata is column vector:
x = zeros(106,25);
for i = 1:106
x(i,:) = [s(i).surveydata]';
end