Mean value of multiple columns - matlab

I have searched a lot to find the solution, but nothing really works for me I think.
I have n data files containing two columns each (imported using uigetfile). To extract the data, I use a for loop like this:
for i=1:n
data{i}=load(filename{i});
x{i}=data{i}(:,1);
y{i}=data{i}(:,2);
end
Now, I want to get the mean value for each row of all the (let's say) x-values. E.g.:
x{1} = [1,4,7,8]
x{2} = [1,2,6,9]
Then I want something like
x_mean = [1,3,6.5,8.5]
I have tried (where k is number of rows)
for i=1:n
data{i}=load(filename{i});
x{i}=data{i}(:,1);
y{i}=data{i}(:,2);
j=1:k
x_mean=sum(x{i}(j))/n
end
But I can't use multiple counters in a for loop (as I understand). Moreover, I don't use mean as I don't see how I can use it in this case.
If someone could help me, it would be great!

You can capture the contents of each numeric array in the cell x into a new numeric array x_num like so:
x_num = [x{:}]
Computing the mean is then as simple as
mean_x = mean( [x{:}] )
For your example, that gives you the mean of all numbers in all arrays in x, which will therefore be a scalar.
If you want to compute the mean of all the rows (column-wise mean), as your example would indicate), you have to concatenate your arrays vertically, which you can do with cat:
mean_x_columnwise = mean( cat(1,x{:}) )
If you want to take the mean over all the columns (row-wise mean), you should only have to tell mean that you are looking at a different dimension:
mean_x_rowwise = mean( cat(1,x{:}), 2)

Related

Matlab -- Copy Structure Array without For Loop

I have a fairly simple question in Matlab. I want to copy n items of structure array (sumRT.P) to a matrix (m). In C, I would just use a for loop, like this:
for i = 1:n
m(i) = sumRT(i).P;
end
But I bet there's a simpler way to copy an array in Matlab (that's the whole point of language right?). I tried this:
m = sumRT(1:n).P;
But this just copies the first item in sumRT.P to m, resulting in a 1 X 1 matrix. Note, if I type, sumRT(2).P for example, I can see the second item. Same for any number up to n. Why is this wrong and how do I fix it?
It depends on the data types in your structure array. If they are types of variables, or if they are variables of the same size in arrays of different dimensions, then you can't put them into an array, but you can make them into a cell:
m={sumRT(1:n).P}
and cells are pretty simple to deal with, so this oughtn't be a big problem.
If they are all scalar numerical values, you can create a matrix:
m=cell2mat({sumRT(1:n).P})
Try the following:
m = squeeze(cell2mat(struct2cell(sumRT(1:n))));
This converts the struct array to a cell array, and then to a (numeric) array, and then squeezes it by remoiving singleton dimensions.
Example:
>> sumRT(1).P = 10; sumRT(2).P = 20; sumRT(3).P = 30;
>> n = 2; %// copy first two elements only
>> m = squeeze(cell2mat(struct2cell(sumRT(1:n))))
m =
10
20

MATLAB: I want to threshold a matrix, based on thresholds in a vector, without a for loop. Possible?

Let us say I have the following:
M = randn(10,20);
T = randn(1,20);
I would like to threshold each column of M, by each entry of T. For example, find all indicies of all elements of M(:,1) that are greater than T(1). Find all indicies of all elements in M(:,2) that are greater than T(2), etc etc.
Of course, I would like to do this without a for-loop. Is this possible?
You can use bsxfun like this:
I = bsxfun(#gt, M, T);
Then I will be a logcial matrix of size(M) with ones where M(:,i) > T(i).
You can use bsxfun to do things like this, but it may not be faster than a for loop (more below on this).
result = bsxfun(#gt,M,T)
This will do an element wise comparison and return you a logical matrix indicating the relationship governed by the first argument. I have posted code below to show the direct comparison, indicating that it does return what you are looking for.
%var declaration
M = randn(10,20);
T = randn(1,20);
% quick method
fastres = bsxfun(#gt,M,T);
% looping method
res = false(size(M));
for i = 1:length(T)
res(:,i) = M(:,i) > T(i);
end
% check to see if the two matrices are identical
isMatch = all(all(fastres == res))
This function is very powerful and can be used to help speed up processes, but keep in mind that it will only speed things up if there is a lot of data. There is a bit of background work that bsxfun must do, which can actually cause it to be slower.
I would only recommend using it if you have several thousand data points. Otherwise, the traditional for-loop will actually be faster. Try it out for yourself by changing the size of the M and T variables.
You can replicate the threshold vector and use matrix comparison:
s=size(M);
T2=repmat(T, s(1), 1);
M(M<T2)=0;
Indexes=find(M);

MATLAB List values above threshold

I have a 3D matrix. I can use the below code to find the number of elements above 1.61. How can I actually list the elements that are above 1.61 and show what value they are? for instance, if I have a value of 8.1 and 9.1, I would like Matlab to tell me those two values. Can I do that?
for i = 1:5
A = ans.atom_data(:,5,i);
count(i,:) = sum(A(:)>1.61)
end
If you only want to know the values, use logical indexing, like this:
result = A(A>1.61);
If you want to obtain the result for each third-index-layer of a 3D array B, you can do it with cells:
result = cellfun(#(x) x(x>1.61), squeeze(mat2cell(B,size(B,1),size(B,2),ones(1,size(B,3)))),'uni',0);
Then result{1} gives the values corresponding to B(:,:,1), etc.

Create matrix of matrix by loading data "MATLAB"

I want make a vector of matrix with loading data of text file.
I am using cat.
n : number of matrices.
p : number of columns of matrices.
every matrix has 4 row.
for example I have 1200 numbers in one text file and p is 3, so n=100.
How can make it?!
This is what I tried to do:
X = cat(n,[1...p; ; ; ],...,[ ; ; ; ]);
The description is a bit vague, but here is what I would recommend:
Read all the data into matlab (It seems like you know how to do this)
Put everything in one big matrix or vector
Only after putting everything together, use the reshape command
In your case you may want to do something like this for step 3:
raw = rand(1200,1); %Assuming your data looks something like this
X = reshape(raw,[],4,3);
For 1200 values this will give you a 100x4x3 answer. Just make sure it is a nice multiple of 4x3 if you apply reshape like this.
Update
Apparently this was the variation the asker was looking for, a 4x3x100 matrix:
X =reshape(r,4,3,100)
If you know the number of matrices (n), you can store it into a cell array like this
myCellArray = cell(n,1);
for it = 1:n
myCellArray{it} = (...) %Load matrix whatever how you do it (Load, fread,...)
end
or just by using dynamic allocation, but not really efficient,
myArray = [];
myArray = [myArray newLoadArray];

How to change row number in a FOR loop... (MATLAB newbie)

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