Store a particular set points in a new cell array - matlab

I had asked a similar question few weeks back but I think that question was not framed properly so please excuse me for asking the same question again
I have a column vector with values
32.5
25.8
25.91
25.92
16.52
16.7
Now I want to create a cell array such that my first cell contains the first value, my second cell array contains value from 25.8 to 25.92 and finally my third cell array contains the values 16.52 and 16.7 .
How can I solve this problem.

Since you didn't explain why you want the vector split up, I assume the specified division is arbitrary. The following should do what you want, assuming v is the column vector:
c = {v(1) v(2:4) v(5:6)};
Basically you are constructing three new vectors out of pieces of the original, and putting them together into a cell array.

This is a way with for loop.
A = [...
32.5
25.8
25.91
25.92
16.52
16.7];
[U,~,ic] = unique(floor(A));
B = cell(length(U),1); % Result
for k = 1:length(A)
B{ic(k)} = [B{ic(k)} A(k)];
end
Thank to unique command the result is even sorted.

Related

Removing rows based on a condition (Matlab)

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.

How to sum up values in corresponding indexes of cells?

I have a 1x24 cell array called chaining, whose each cell contains a 119x119 matrix:
I want to find the sum of each corresponding elements of all the cells, and store them in a matrix called result. That is, the (j,k)th element of result should contains the sum of the (j,k)th elements of all the matrices in the cell array chaining.
The code I wrote to do this is:
for j=1:size(chaining,2)
for k=1:size(chaining,2)
result(j,k) = sum(chaining{1,:}(j,k));
end
end
But this gives error because apparently MATLAB can't aggregate cell arrays for some reason (i.e., the chaining{1,:} part).
Could anyone please show me how to go about doing this?
how about
result = sum( cat(3, chaining{:}), 3 );
What just happened here?
First, we convert the cell array into a 3D array by "stacking" the 2D cell elements on the third dimension:
cat(3, chaining{:})
Once we have a 3D array of size 119-by-119-by-24 we can sum along the third dimension and get result of size 119-by-119:
sum( ..., 3 );
For more info see cat and sum help pages.
BTW,
If you insist on chaining{1,:}(jj,kk) type of solution (not recommended), you might find subsref command useful.

Printing progress in command window

I'd like to use fprintf to show code execution progress in the command window.
I've got a N x 1 array of structures, let's call it myStructure. Each element has the fields name and data. I'd like to print the name side by side with the number of data points, like such:
name1 number1
name2 number2
name3 number3
name4 number4
...
I can use repmat N times along with fprintf. The problem with that is that all the numbers have to come in between the names in a cell array C.
fprintf(repmat('%s\t%d',N,1),C{:})
I can use cellfun to get the names and number of datapoints.
names = {myStucture.name};
numpoints = cellfun(#numel,{myStructure.data});
However I'm not sure how to get this into a cell array with alternating elements for C to make the fprintf work.
Is there a way to do this? Is there a better way to get fprintf to behave as I desire?
You're very close. What I would do is change your cellfun call so that the output is a cell array instead of a numeric array. Use the 'UniformOutput' flag and set this to 0 or false.
When you're done, make a new cell array where both the name cell array and the size cell array are stacked on top of each other. You can then call fprintf once.
% Save the names in a cell array
A = {myStructure.name};
% Save the sizes in another cell array
B = cellfun(#numel, {myStructure.data}, 'UniformOutput', 0);
% Create a master cell array where the first row are the names
% and the second row are the sizes
out = [A; B];
% Print out the elements side-by-side
fprintf('%s\t%d\n', out{:});
The trick with the third line of code is that when you unroll the cell array using {:}, this creates a comma-separated list unrolled in column-major format, and so doing out{:} actually gives you:
A{1}, B{1}, A{2}, B{2}, ..., A{n}, B{n}
... which provides the interleaving you need. Therefore, providing this order into fprintf coincides with the format specifiers that are specified and thus gives you what you need. That's why it's important to stack the cell arrays so that each column gives the information you need.
Minor Note
Of course one should never forget that one of the easiest ways to tackle your problem is to just use a simple for loop. Even though for loops are considered bad practice, their performance has come a long way throughout MATLAB's evolution.
Simply put, just do this:
for ii = 1 : numel(myStructure)
fprintf('%s\t%d\n', myStructure(ii).name, numel(myStructure(ii).data));
end
The above code is arguably more readable in comparison to what we did above with cell arrays. You're accessing the structure directly rather than having to create intermediate variables for the purpose of calling fprintf once.
Example Run
Here's an example of this running. Using the data shown below:
clear myStructure;
myStructure(1).name = 'hello';
myStructure(1).data = rand(5,1);
myStructure(2).name = 'hi';
myStructure(2).data = zeros(3,3);
myStructure(3).name = 'huh';
myStructure(3).data = ones(6,4);
I get the following output after running the printing code:
hello 5
hi 9
huh 24
We can see that the sizes are correct as the first element in the structure is simply a random 5 element vector, the second element is a 3 x 3 = 9 zeroes matrix while the last element is a 6 x 4 = 24 ones matrix.

In an assignment A(:) = B, the number of elements in A and B must be the same

if (hidden_layer>1)
for i =1 :hidden_layer
start_hidden_layer(i) = rand([gk(i+1),(gk(i)+1)])-0.5 ;
end
end
hi Friends.
I know every iteration was changed start_hidden_layer matrix dimensional.But all start_hidden_layer values must saved. How to solve this problem?
firstly hidden_layer>1
gk(i) is integer value for example 5 , 3, 8
Since you're calling rand with different matrix sizes on each iteration, you cannot save the results into a normal matrix. You need to use a cell matrix to store the result, like this:
%//preallocate the cell array
start_hidden_layer = cell(1, hidden_layer);
for i = 1:hidden_layer
start_hidden_layer{i} = rand([gk(i+1), (gk(i)+1)]) - 0.5;
end
For more on cell arrays and how to use them, see this Mathworks help doc.

Fastest way of finding repeated values in different cell arrays of different size

The problem is the following:
I have a cell array of the form indx{jj} where each jj is an array of 1xNjj, meaning they all have different size. In my case max(jj)==3, but lets consider a general case for the shake of it.
How would you find the value(s) repeated in all the jj i the fastest way?
I can guess how to do it with several for loops, but is there a "one (three?) liner"?
Simple example:
indx{1}=[ 1 3 5 7 9];
indx{2}=[ 2 3 4 1];
indx{3}=[ 1 2 5 3 3 5 4];
ans=[1 3];
One possibility is to use a for loop with intersect:
result = indx{1}; %// will be changed
for n = 2:numel(indx)
result = intersect(result, indx{n});
end
Almost no-loop approach (almost because cellfun essentially uses loop(s) inside it, but it's effect here is minimal as we are using it to find just the number of elements in each cell) -
lens = cellfun(#numel,indx);
val_ind = bsxfun(#ge,lens,[1:max(lens)]');
vals = horzcat(indx{:});
mat1(max(lens),numel(lens))=0;
mat1(val_ind) = vals;
unqvals = unique(vals);
out = unqvals(all(any(bsxfun(#eq,mat1,permute(unqvals,[1 3 2]))),2));
Another possibility that I could suggest, though Luis Mendo's answer is very good, is to take all of the vectors in your cell array and remove the duplicates. This can be done through cellfun, and specifying unique as the function to operate on. You'd have to set the UniformOutput flag to false as we are outputting a cell array at each index. You also have to be careful in that each cell array is assumed to be all row vectors, or all column vectors. You can't mix the way the arrays are shaped or this method won't work.
Once you do this, concatenate all of the vectors into a single array through cell2mat, then do a histogram through histc. You'd specify the edges to be all of the unique numbers in the single array created before. Note that you'd have to make an additional call to unique on the output single array before proceeding. Once you calculate the histogram, for any entries with a bin count equal to the total number of elements in your cell array (which is 3 in your case), then these are values that you see in all of your cells. As such:
A = cell2mat(cellfun(#unique, indx, 'uni', 0));
edge_values = unique(A);
h = histc(A, edge_values);
result = edge_values(h == numel(indx));
With the unique call for each cell array, if a number appears in every single cell, then the total number of times you see this number should equal the total number of cells you have.