Compare length of multiple array and display error if unequal - matlab

I have multiple array of real numbers.
Eg.
a = [1:5]
b = [11:15]
c = [100:105]
d = [200:210]
I want a shorter code, if number of arrays are in 100's. What i know is,
if length(a) == length(b) && length(b) == length(c) && length(c)== length(d)
else
error ('Length of data series is unequal. Correct it.')
end
This will display an error if length if all series is not equal but how could it be done in small code when array number and size is very large (in 100's) ?
Thank you.

Code
%%// Get all the arrays/vectors into a cell array, with each element in each cell
A = [{a},{b},{c},{d}]
%%// Get the number of elements of all the cells, that is number of elements
%%// of all vectors into an array. This, this array could be thought of as an
%%// array of sizes
numels = cellfun(#numel,A)
%%// Now that we have an array of sizes, we need to make sure that
%%//all the sizes are same. So when we compare all sizes to
%%// any randomly picked one (first one in this case), must be matching,
%%// which is being covered by the command - all.
if ~all(numels==numels(1))
error ('Length of data series is unequal. Correct it.')
end

Related

Using Matlab to randomly split an Excel Sheet

I have an Excel sheet containing 1838 records and I need to RANDOMLY split these records into 3 Excel Sheets. I am trying to use Matlab but I am quite new to it and I have just managed the following code:
[xlsn, xlst, raw] = xlsread('data.xls');
numrows = 1838;
randindex = ceil(3*rand(numrows, 1));
raw1 = raw(:,randindex==1);
raw2 = raw(:,randindex==2);
raw3 = raw(:,randindex==3);
Your general procedure will be to read the spreadsheet into some matlab variables, operate on those matrices such that you end up with three thirds and then write each third back out.
So you've got the read covered with xlsread, that results in the two matrices xlsnum and xlstxt. I would suggest using the syntax
[~, ~, raw] = xlsread('data.xls');
In the xlsread help file (you can access this by typing doc xlsread into the command window) it says that the three output arguments hold the numeric cells, the text cells and the whole lot. This is because a matlab matrix can only hold one type of value and a spreadsheet will usually be expected to have text or numbers. The raw value will hold all of the values but in a 'cell array' instead, a different kind of matlab data type.
So then you will have a cell array valled raw. From here you want to do three things:
work out how many rows you have (I assume each record is a row) by using the size function and specifying the appropriate dimension (again check the help file to see how to do this)
create an index of random numbers between 1 and 3 inclusive, which you can use as a mask
randindex = ceil(3*rand(numrows, 1));
apply the mask to your cell array to extract the records matching each index
raw1 = raw(:,randindex==1); % do the same for the other two index values
write each cell back to a file
xlswrite('output1.xls', raw1);
You will probably have to fettle the arguments to get it to work the way you want but be sure to check the doc functionname page to get the syntax just right. Your main concern will be to get the indexing correct - matlab indexes row-first whereas spreadsheets tend to be column-first (e.g. cell A2 is column A and row 2, but matlab matrix element M(1,2) is the first row and the second column of matrix M, i.e. cell B1).
UPDATE: to split the file evenly is surprisingly more trouble: because we're using random numbers for the index it's not guaranteed to split evenly. So instead we can generate a vector of random floats and then pick out the lowest 33% of them to make index 1, the highest 33 to make index 3 and let the rest be 2.
randvec = rand(numrows, 1); % float between 0 and 1
pct33 = prctile(randvec,100/3); % value of 33rd percentile
pct67 = prctile(randvec,200/3); % value of 67th percentile
randindex = ones(numrows,1);
randindex(randvec>pct33) = 2;
randindex(randvec>pct67) = 3;
It probably still won't be absolutely even - 1838 isn't a multiple of 3. You can see how many members each group has this way
numel(find(randindex==1))

Adding 0's to cell array such that each column contains an equal number of entries - MATLAB

I have a 16x100 (varies in size) cell array and I would like to extract each of it's columns into a column of a matrix. When each column of the cell array contains an identical number of entries I can use:
elem = numel([dist{:,1}]);
repeat = size(dist,2);
data = zeros(elem,repeat);
for k=1:repeat
results(:,k) = [dist{:,k}]';
end
However there are some instances where there are not an equal number thus it returns the error:
Subscripted assignment dimension mismatch.
What is the best way around this? Is there a way to add zeroes to equalise the number of entries?
Perfect setup for bsxfun's masking capability here!
Now, I am assuming your data is setup as described in your previous question -
To solve the case of filling up "empty spaces" with zeros, you can setup an output array with maximum possible number of elements in each column and then fillup the valid spaces with the values from the input cell array, with the valid spaces being detected by the logical mask created with bsxfun. Read on through the comments inlined within the code listed next to find out the exact ideas on solving it -
%// Get the number of elements in each column of the input cell array
lens = sum(cellfun('length',a),1)
%// Store the maximum number of elements possible in any column of output array
max_lens = max(lens)
%// Setup output array, with no. of rows as max number of elements in each column
%// and no. of columns would be same as the no. of columns in input cell array
results = zeros(max_lens,numel(lens))
%// Create as mask that has ones to the "extent" of number of elements in
%// each column of the input cell array using the lengths
mask = bsxfun(#le,[1:max_lens]',lens) %//'
%// Finally, store the values from input cell array into masked positions
results(mask) = [a{:}]

How to compare two cell elements in matlab?

I am using two cells for storing the targeted and the expected value of a neural network process in matlab. I have used two 1*1 cell array for storing the values respectively. And here is my code.
cinfo=cell(1,2)
cinfo(1,1)=iter(1,10)%value is retrieved from a dataset iter
cinfo(1,2)=iter(1,11)
amp1=cinfo(1,1);
amp2=cinfo(1,2);
if amp1 == amp2
message=sprintf('NOT DETECTED BY THE DISEASE');
uiwait(msgbox(message));
But when i run the above code, the get the following error :
??? Undefined function or method 'eq' for input arguments of type 'cell'.
Error in ==> comparison at line 38
if amp1 == amp2
How to solve this problem?
The problem is how you indexed things. A 1x1 cell array does not make a lot of sense, instead get the actual element in the single cell, by indexing with curly brackets:
amp1=cinfo{1,1}; # get the actual element from the cell array, and not just a
amp2=cinfo{1,2}; # 1x1 cell array by indexing with {}
if (amp1 == amp2)
## etc...
However, note that if amp1 and amp2 are not scalars the above will act weird. Instead, do
if (all (amp1 == amp2))
## etc...
Use isequal. That will work even if the cell's contents have different sizes.
Example:
cinfo=cell(1,2);
cinfo(1,1) = {1:10}; %// store vector of 10 numbers in cell 1
cinfo(1,2) = {1:20}; %// store vector of 20 numbers in cell 2
amp1 = cinfo(1,1); %// single cell containing a length-10 numeric vector
amp2 = cinfo(1,2); %// single cell containing a length-20 numeric vector
if isequal(amp1,amp2)
%// ...
In this example, which parallels your code, amp1 and amp2 are cell arrays consisting of a single cell which contains a numeric vector. Another possibility is to directly store each cell's contents into amp1, amp2, and then compare them:
amp1 = cinfo{1,1}; %// length-10 numeric vector
amp2 = cinfo{1,2}; %// length-20 numeric vector
if isequal(amp1,amp2)
%// ...
Note that even in this case, the comparisons amp1==amp1 or all(amp1==amp2) would give an error, because the vectors have different sizes.

How to sum the values of an MxN cell array?

How can I make the sum of values in an MxN cell array? I used cellfun('sum',CellArray{i})
in which, i refers to the MxN index of the CellArray. But because I used it in a loop to count the number of blocks, it gives me error for being out of index.
What's the right way to do that please?
I don't know if I got your problem entirely right. You just want the total sum of all elements of a cell array? Assuming they are doubles, you first need to transform your cell array into a matrix, and then you can use the normal sum function.
% example data
xCell = num2cell( magic(10) )
gives you a a 10x10 cell array with some magic numbers from 1 to 100.
The following creates a column-vector of all cell contents and sums them up:
S = sum([xCell{:}])
S =
5050
which is the result good ol' Mr. Gauss didn't need Matlab for.
Alternatively if you're interested in the sum of all single rows or columns, you can use:
S = sum(cell2mat(xCell),dimension) % dimension = 1 or 2 (or 3)
regarding your comment in your follow-up question, that you actually have complex doubles:
use:
S = sum( real( [xCell{:}] ) )

MATLAB busy, loop works well until i=29996, when i=29997 stay Busy

I am writing code which compares the data of a vector. It should count how many positions (acc) have equal values, and save a specific value in a vector of the same length of the quantity of positions (n_T(acc)).
My data vector is [30000 x 1]. For example, first 80 positions have the same value, next 60 positions have the same value, etc., next 5 positions have the same value.
The code works well if I use just 29996 values. I do not understand why when I try to use the complete vector MATLAB stays Busy.
Checking my data vector, I noticed that the last 5 positions are equivalent [29996:30000]. Could it be the reason, and what should I change?
Following is the code
%========================================================
%ac: data vector`
%acc1: accumulator which count how much positions have the same value
%n_T: vector which presents the values I need, in the same positions the data is equal
%m: show a value where i should begin
%========================================================
i=m; %previously used`
fv=length(ac)
while i<fv %29996
acc1=0;
for i=m+1:fv
if ac(i)==ac(i-1)
acc1=acc1+1; % count how much positions are equals
else
m=i;
break
end
end
mi=m-acc1; %define where the data n_T should begin
for i=mi:m
n_T(i)=tm/acc1; %create a vector with length [acc x1] begining in mi and finishing in m
end
m=i;
end
plot(n_T)
Does it work if you do this in a vectorized way? Not completely sure what you want the program to output.
% locate repeated elements
eq_els = ac(diff(ac) == 0);
% count number of repeated elements (unique)
unique_els = unique(eq_els);
num_equal_els = numel(unique_els);
% create variable-length lists for each unique element
each_eq_list = cell(num_equal_els,1);
for (k = 1:num_equal_els)
% each vector in the cell array is equal to the elements of ac that are equal to the current unique item
each_eq_list{[k]} = ac(ac == unique_els(k));
end
The length of each_eq_list{[k]} is the length of the total number of contiguous repeated values of repeated value k.