combine rows of multiple arrays of a cell to one new array - arrays

There is a cell with five arrays. Each array consits of two rows and 30 columns. Now i want one array with the values in the first rows of the arrays merged.
cellC{1,1} = arrayA1 = [1 2 3; 4 5 6]
cellC{1,2} = arrayA2 = [11 12 13; 14 15 16]
....
I want to get the array
[1 2 3 11 12 13]
Indexing like the following does not work:
cellC{1, 1:5}(1,:)
I thought of a for-loop but there must be a simpler solution. I hope you can help me. Thank you very much!

You can utilize {:} indexing to create a comma separated list that you can then pass to cat to concatenate all of the cell contents horizontally. You can then select out the first row from the resulting matrix.
tmp = cat(2, cellC{:});
result = tmp(1,:);

Related

how to eliminate repeating integers from cell array in matlab

i have [words*sentences]matrix where sentences have integers that represent sentence numbers from a text document from this matrix i have constructed 1D array of [1*N] which shows words and in which sentences they occur number wise.
once above step is done i have taken intersection to check which words occur together in which sentences the code is as follows:
OccursTogether = cell(length(Out1));
for ii=1:length(Out1)
for jj=ii+1:length(Out1)
OccursTogether{ii,jj} = intersect(Out1{ii},Out1{jj});
end
end
celldisp(OccursTogether)
the sample output is as follows which shows 1st word occurs in sentence
{5 10 16} same word occurs with 2nd word in sentence {11 12 13} and word 1 occurs with word 3 in sentence {9 14} and so on till the Nth word:
OccursTogether{1,1} = 5 10 16
OccursTogether{2,1} = 5 12 16
OccursTogether{3,1} = 9 14
now what i want is to show output in one line based upon OccursTogether cell array without repeating sentence numbers as below:
output: {5 9 10 12 14 16}
any help would me appreciated..
If I understand correctly:
result = unique([OccursTogether{:}]);
In your example this gives
result =
5 9 10 12 14 16
Here is a way using cellfun and cell2mat. The idea is to vertically concatenate each cell form the cell array, convert it to a matrix and apply the unique function.
So the first step:
a = cellfun(#(x) x.',OccursTogether,'uni',false)
Takes each cell and transpose it, thus making a n x 1 vector. The result is a cell array containing vertical vectors:
a =
[3x1 double]
[3x1 double]
[2x1 double]
Now we can use cell2mat to convert to a numeric matrix since the dimensions will fit and finally apply unique. Otherwise that would not be possible (eg using 1x3 and 1x2 vectors).
In 1 line that looks like this:
output = unique(cell2mat(cellfun(#(x) x.',OccursTogether,'uni',false)))
output =
5
9
10
12
14
16
Hope this is what you meant! If not please tell me.

how can i call up either part of the results like (e1,e5,e6,e9)or (from e1 to e7) in matlab? then i need to combine them in one array in matlab

if i have a lot of arrays with different dimensions and their names take the following forms :e1,e2,e3,...,e10 and so on. how can i call up either part of the results like (e1,e5,e6,e9)or (from e1 to e7)? then i need to combine them in one array . for your information , these array names resulted from this code :
{clc
clear
a=input('please, select your array :')
b=a(:)'
c=length(b)
for d=1:c
if (d<c)
eval(sprintf('e%d = nchoosek(b,%d)', d,d))
end
end}
what i need is, combine matrices like (e1,e2,e3,e4) vertically meaning that each matrix under other in one matrix not each element of all matrices under each other .
Notes:- empty cells do not include numbers will be produced resulting from the different sizes of the matrices when combining them ,then, i want to pad these cells with zeros
First off: Using eval for creating variable names is bad practice. I suggest you change your code to the following:
a = input('Please, select your array: ')
b = a(:).'
c = length(b)
for d =1:c
if (d<c)
e{d} = nchoosek(b, d);
end
end
Updated answer:
Following your comment:
You can use padarray to insert zeros so that all cells have the same number of columns. cellfun is used in order to do the same operations on each cell.
cellfun(#(m) padarray(m,[0 max(cellfun(#(n) size(n,2), e)) - size(m,2)],'post'), e,'UniformOutput',0)
Columns 1 through 5
[7x6 double] [21x6 double] [35x6 double] [35x6 double] [21x6 double]
Column 6
[7x6 double]
Now all matrices have the same number of columns and you can combine them in any way you want, for instance using cell2mat like this.
cell2mat(x([1 3 5])')
Original answer:
Now you say you want to combine all the matrices vertically. You can do this by combining cell2mat and cellfun like this:
cell2mat(cellfun(#(n) n(:), e, 'UniformOutput',0)')
If you only want number 1 and 3 you can do:
cell2mat(cellfun(#(n) n(:), e([1 3]), 'UniformOutput',0)')
The cellfun-part is equivalent to:
k = 1;
for ii = [1 3]
f{k} = e{ii}(:);
k = k + 1;
end
cell2mat concatenates the cells vertically.
This does the same as if you wanted to align the two following vectors vertically:
a = [1 3; 2 4];
b = [5 8 11; 6 9 12; 7 10 13];
c = [a(:); b(:)]
c =
1
2
3
4
5
6
7
8
9
10
11
12
13

Avoid loops in matlab

I am limited in the use of cycles in matlab and I have one task. I have the matrix 2xn with numbers and cell array 1xn. Each element in the first row point to a position of the array. I want to add every number from the second row of matrix to cell, which is pointed by corresponding number in the first row. In addition, I want the cells to be strings.
Let me clarify with example:
A = [[1 4 3 3 1 4 2], [7 4 3 5 6 5 4]]
I want to get array of cells: {'76', '4', '35', '45'}
How can I do this without using a for or while loop?
A = [1 4 3 3 1 4 2; 7 4 3 5 6 5 4]; %// data: 2 x n array
[~, ~, ii] = unique(A(1,:));
R = accumarray(ii(:),A(2,:),[],#(v) {fliplr(regexprep(num2str(v(:).'),'\s',''))}).';
The second line (unique) is used to remove possible gaps in first row. Otherwise those gaps would translate to the result of accumarray, which would then take up more memory uselessly.
The third line (accumarray) aggregates all values of second row of A that have the same value in the first row. The aggregation is done by the anonymous function, which converts numbers to string (num2str), removes spaces (regexprep), and changes orientation (fliplr and .') to match the desired output format.
EDIT:
Thanks to #chappjc's suggestion, the third line can be simplified to
R = accumarray(ii(:),A(2,:),[],#(v) {fliplr(num2str(v(:).','%d'))}).';
Alright, by just pointing at cellfun, arrayfun, cell2mat, cell indexing and array indexing I was arrogant. So, I try to make it up by actually using some of those in a more constructive solution:
%// Using array-indexing to find all matches with the current index in the first row,
%// then print their counterpart(s) into strings
fun = #(ii) sprintf('%d', A(2, A(1, :) == ii));
%// The following could also be 1:size(A, 2) or unique(A(1, :)) depending on the
%// general form of your problem.
range = min(A(1, :)) : max(A(1, :));
%// Using arrayfun to loop over all values in the first row
R = arrayfun(fun, range, 'UniformOutput', false)

Easiest way to create arrays based on repeating character positions

I want to group my elements using the repeated segments in the array. The breaking is basically depend on where the repeated segments are, in my real data contains ~10000 elements and I want to know if there is a easier way to do that.
Here is a short example to clarify what I want:
Let's say I have an array,
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
What I want is to break A into [1 5 3],[6 9], and [9 5 2];
What is the easiest to code this using matlab??
Thanks.
For a vectorized solution, you can find out the places where either forward or backward differences to the neighbor are zero, and then use bwlabel (from the Image Processing Toolbox) and accumarray to gather the data.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
d = diff(A)==0;
%# combine forward and backward difference
%# and invert to identify non-repeating elments
goodIdx = ~([d,false]|[false,d]);
%# create list of group labels using bwlabel
groupIdx = bwlabel(goodIdx);
%# distribute the data into cell arrays
%# note that the first to inputs should be n-by-1
B = accumarray(groupIdx(goodIdx)',A(goodIdx)',[],#(x){x})
EDIT
Replace the last two lines of code with the following if you want the repeating elements to appear in the cell array as well
groupIdx = cumsum([1,abs(diff(goodIdx))]);
B = accumarray(groupIdx',A',[],#(x){x})
EDIT2
If you want to be able to split consecutive groups of identical numbers as well, you need to calculate groupIdx as follows:
groupIdx = cumsum([1,abs(diff(goodIdx))|~d.*~goodIdx(2:end)])
Here is a solution that works if I understand the question correctly. It can probably be optimised further.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
% //First get logical array of non consecutive numbers
x = [1 (diff(A)~=0)];
for nn=1:numel(A)
if ~x(nn)
if x(nn-1)
x(nn-1)=0;
end
end
end
% //Make a cell array using the logical array
y = 1+[0 cumsum(diff(find(x))~=1)];
x(x~=0) = y;
for kk = unique(y)
B{kk} = A(x==kk);
end
B{:}

How can I concatenate ranges of numbers into an array in MATLAB?

For example, I want to combine two ranges of numbers like this:
1 2 3 4 5 11 12 13 14 15 16 17 18 19 20
So, I tried:
a = 1:5,11:20
but that didn't work.
I also want to do this in a non-hardcoded way so that the missing 5 elements can start at any index.
For your example, you need to use square brackets to concatenate your two row vectors:
a = [1:5 11:20];
Or to make it less hardcoded:
startIndex = 6; %# The starting index of the 5 elements to remove
a = [1:startIndex-1 startIndex+5:20];
You may also want to check out these related functions: HORZCAT, VERTCAT, CAT.
There are a few other ways you could do this as well. For one, you could first make the entire vector, then index the elements you don't want and remove them (i.e. set them to the empty vector []):
a = 1:20; %# The entire vector
a(6:10) = []; %# Remove the elements in indices 6 through 10
You could also use set operations to do this, such as the function SETDIFF:
a = setdiff(1:20,6:10); %# Get the values from 1 to 20 not including 6 to 10

Resources