Displaying the output of a cell in matlab - matlab

I have a cell of the of the following :
displayop =
[2114x1 datetime] [2114x1 double] [2114x1 double] {2114x1 cell}
How I can see the output of displayop ? I have tried using cell2mat, but gives me the following error: All contents of the input cell array must be of the same data type.
I am looking at the below output for displayop:
03/11/2016 7544 7544 'UP'

Here is an example using MATLAB's tables:
% a sample cell array resembling your data
>> displayop = {datetime(2016,3,(1:10)') (1:10)' rand(10,1) cellstr(num2str((11:20)'))}
displayop =
[10x1 datetime] [10x1 double] [10x1 double] {10x1 cell}
Now:
% convert to table, which is displayed nicely
>> table(displayop{:}, 'VariableNames',{'dt','x','y','str'})
ans =
dt x y str
___________ __ ________ ____
01-Mar-2016 1 0.049654 '11'
02-Mar-2016 2 0.90272 '12'
03-Mar-2016 3 0.94479 '13'
04-Mar-2016 4 0.49086 '14'
05-Mar-2016 5 0.48925 '15'
06-Mar-2016 6 0.33772 '16'
07-Mar-2016 7 0.90005 '17'
08-Mar-2016 8 0.36925 '18'
09-Mar-2016 9 0.1112 '19'
10-Mar-2016 10 0.78025 '20'
Bonus:
You can still use plain old cell-arrays:
>> C = [num2cell(displayop{1}) num2cell(displayop{2}) num2cell(displayop{3}) displayop{4}]
C =
[01-Mar-2016] [ 1] [0.0497] '11'
[02-Mar-2016] [ 2] [0.9027] '12'
[03-Mar-2016] [ 3] [0.9448] '13'
[04-Mar-2016] [ 4] [0.4909] '14'
[05-Mar-2016] [ 5] [0.4893] '15'
[06-Mar-2016] [ 6] [0.3377] '16'
[07-Mar-2016] [ 7] [0.9001] '17'
[08-Mar-2016] [ 8] [0.3692] '18'
[09-Mar-2016] [ 9] [0.1112] '19'
[10-Mar-2016] [10] [0.7803] '20'

Related

List cell contents in two columns of MATLAB cell array

I'm trying to display the contents of a cell array, which contain two columns, in a nice two column format in the command window.
tmp = [1:10]';
a{:,1} = tmp;
a{:,2} = dec2hex(tmp);
celldisp(a)
I would like the output to have the decimal values in the first column and hex values in the second column. Unfortunately I get:
celldisp(a)
a{1} =
1
2
3
4
5
6
7
8
9
10
a{2} =
1
2
3
4
5
6
7
8
9
A
I am trying to get something that looks more like this:
I also tried the table function but this gave:
Use num2cell to place each element of a into a separate cell.
disp([num2cell(a{1}) num2cell(a{2})]);
%Output:
% [ 1] '1'
% [ 2] '2'
% [ 3] '3'
% [ 4] '4'
% [ 5] '5'
% [ 6] '6'
% [ 7] '7'
% [ 8] '8'
% [ 9] '9'
% [10] 'A'

Indexing Cell arrays for more efficient performance

I have the following code to display a 9-by-3 cell array:
data = cell (9,3);
col1 = [2, 3, 5, 7, 8, 11, 12, 15, 16];
col2 = {[1 1], [1 5], [3 9], [4 2], [4 6], [6 2], [7 6], [6 9], [9 9]};
col3 = {[2 3 4 5 8],[1 3 5 8],[1 2 5 7 8],[1 2 3 6 7],[3 4 7 8],[2 4 8 9],[2 4 5 9],[4 5 7 9],[2 6 7 8]};
k = length(data);
for i = 1:k
data{i,1} = col1(i);
data{i,2} = col2{i};
data{i,3} = col3{i};
end
data
Please, can this code be more efficiently written using a form of indexing? Thanks.
Your have written code to assign a 9 x 3 cell array, which can also be written as:
data2 = [num2cell(col1') col2' col3']
data2 =
[ 2] [1x2 double] [1x5 double]
[ 3] [1x2 double] [1x4 double]
[ 5] [1x2 double] [1x5 double]
[ 7] [1x2 double] [1x5 double]
[ 8] [1x2 double] [1x4 double]
[11] [1x2 double] [1x4 double]
[12] [1x2 double] [1x4 double]
[15] [1x2 double] [1x4 double]
[16] [1x2 double] [1x4 double]

Grouping elements of one column of matrix according to values of another column into cell array

I've been trying to come up with a smart way of doing this for a while. Given a matrix (or cell) with the following structure:
A = [-1 1
-1 2
1 3
3 5
2 3
2 4
2 7
4 5
5 6
6 7
7 -2 ]
(Note that the above matrix/cell is unsorted in both columns and contains negative numbers).
How could one group it by the unique values of a particular column. E.g. the desired output for grouping by the second column would be something like:
B{1} = [-1]
B{2} = [-1]
B{3} = [1,2]
B{4} = [2]
B{5} = [3,4]
B{6} = [5]
B{7} = [2,6]
B{-2} = [7]
Thanks in advance!
You can use accumarray:
[~,~,subs] = unique(A(:,2));
values = accumarray(subs,A(:,1),[],#(x) {x});
ofGroup = accumarray(subs,A(:,2),[],#(x) {x(1)});
out = [ofGroup values]
out =
[-2] [ 7]
[ 1] [ -1]
[ 2] [ -1]
[ 3] [2x1 double]
[ 4] [ 2]
[ 5] [2x1 double]
[ 6] [ 5]
[ 7] [2x1 double]
If you REALLY insist on your order proposed, you could do the following, but I don't think that should be necessary.
% positives
pos = A( A(:,2) >= 0 , :);
[~,~,subs] = unique(pos(:,2));
posvalues = accumarray(subs,pos(:,1),[],#(x) {x});
posofGroup = accumarray(subs,pos(:,2),[],#(x) {x(1)});
% negatives
neg = A( A(:,2) < 0 , :);
[~,~,subs] = unique(neg(:,2));
negvalues = flipud( accumarray(subs,neg(:,1),[],#(x) {x}) );
negofGroup = flipud( accumarray(subs,neg(:,2),[],#(x) {x(1)}) );
out = [posofGroup posvalues; negofGroup negvalues ]
out =
[ 1] [ -1]
[ 2] [ -1]
[ 3] [2x1 double]
[ 4] [ 2]
[ 5] [2x1 double]
[ 6] [ 5]
[ 7] [2x1 double]
[-2] [ 7]
How about:
[group, ~, subs] = unique(A(:,2))
B = accumarray(subs, A(:,1), [], #(x){x'})
Results in
B=
[ 7]
[ -1]
[ -1]
[2,1]
[ 2]
[4,3]
[ 5]
[2,6]
and group matches the index of B to the number of the group it represents
Also if you are attached to your ordering then you can do this:
[group, ~, subs] = unique(A(end:-1:1,2), 'stable');
B = flipud(accumarray(subs, A(end:-1:1,1), [], #(x){x'}));
group = flipud(group);
B =
[ -1]
[ -1]
[1x2 double]
[ 2]
[1x2 double]
[ 5]
[1x2 double]
[ 7]
group =
1
2
3
4
5
6
7
-2

Elegant way of stripping the 1st layer of cell array in MATLAB?

I have a 1x2 cell array a such that
a{1, 1} is a 5x1 int array containing [1 2 3 4 5]
a{1, 2} is a 5x1 cell array containing 'aa', 'bb', 'cc', 'dd', 'ee'
What is the most elegant way of stripping the first layer, producing a 5x2 cell array as follows?
1 'aa'
2 'bb'
3 'cc'
4 'dd'
5 'ee'
How about:
% original cell
a = cell(1,2);
a{1} = [1 2 3 4 5];
a{2} = {'aa', 'bb', 'cc', 'dd', 'ee'};
% flattened
aa = reshape([num2cell(a{1}) a{2}], [], 2)
I figured one solution out, but am not sure about its "elegantness".
a = cell(1, 2);
a{1, 1} = [1, 2, 3, 4, 5];
a{1, 2} = {'aa','bb','cc','dd','ee'};
result = [num2cell(a{1, 1})' a{1, 2}']
result =
[1] 'aa'
[2] 'bb'
[3] 'cc'
[4] 'dd'
[5] 'ee'
You can try this code:
a{1, 1} = [1,2,3,4,5];
a{1, 2} = {'aa','bb','cc','dd','ee'};
temp = num2cell(a{1});
b = {temp{:};a{2}{:}}.'
b =
[1] 'aa'
[2] 'bb'
[3] 'cc'
[4] 'dd'
[5] 'ee'

Joining data from different cell arrays in Matlab

I have data in Matlab that is in cell array format with columns representing different items. The cell arrays have different columns, as in the following example:
a = {'A', 'B', 'C' ; 1, 1, 1; 2, 2, 2 }
a =
'A' 'B' 'C'
[1] [1] [1]
[2] [2] [2]
b = {'C', 'D'; 3, 3; 4, 4}
b =
'C' 'D'
[3] [3]
[4] [4]
I would like to be able to join the different cell arrays in the following manner:
c =
'A' 'B' 'C' 'D'
[1] [1] [1] [NaN]
[2] [2] [2] [NaN]
[NaN] [NaN] [3] [3]
[NaN] [NaN] [4] [4]
In the real example I have hundreds of columns and several rows, so creating a new cell array manually is not an option for me.
If you were willing to store your data in dataset arrays (or convert them to dataset arrays for this purpose), you could do the following:
>> d1
d1 =
A B C
1 1 1
2 2 2
>> d2
d2 =
C D
3 3
4 4
>> join(d1,d2,'Keys','C','type','outer','mergekeys',true)
ans =
A B C D
1 1 1 NaN
2 2 2 NaN
NaN NaN 3 3
NaN NaN 4 4
I'm assuming you want to join the two arrays based on their first row only.
% get the list of all keys
keys = unique([a(1,:) b(1,:)]);
lena = size(a,1)-1; lenb = size(b,1)-1;
% allocate space for the joined array
joined = cell(lena+lenb+1, length(keys));
joined(1,:) = keys;
% add a
tf = ismember(keys, a(1,:));
joined(2:(2+lena-1),tf) = a(2:end,:);
% add b
tf = ismember(keys, b(1,:));
joined((lena+2):(lena+lenb+1),tf) = b(2:end,:);
This will give you the joined array except that it has empty cells instead NaNs. I hope this is OK.
Here is my solution adapted from an old another to a similar question (simply transpose rows/columns):
%# input cell arrays
a = {'A', 'B', 'C' ; 1, 1, 1; 2, 2, 2 };
b = {'C', 'D'; 3, 3; 4, 4};
%# transpose rows/columns
a = a'; b = b';
%# get all key values, and convert them to indices starting at 1
[allKeys,~,ind] = unique( [a(:,1);b(:,1)] );
indA = ind(1:size(a,1));
indB = ind(size(a,1)+1:end);
%# merge the two datasets (key,value1,value2)
c = cell(numel(allKeys), size(a,2)+size(b,2)-1);
c(:) = {NaN}; %# fill with NaNs
c(:,1) = allKeys; %# available keys from both
c(indA,2:size(a,2)) = a(:,2:end); %# insert 1st dataset values
c(indB,size(a,2)+1:end) = b(:,2:end); %# insert 2nd dataset values
Here is the result (transposed to match original orientation):
>> c'
ans =
'A' 'B' 'C' 'D'
[ 1] [ 1] [1] [NaN]
[ 2] [ 2] [2] [NaN]
[NaN] [NaN] [3] [ 3]
[NaN] [NaN] [4] [ 4]
Also here is the solution using the DATASET class from the Statistics Toolbox:
aa = dataset([cell2mat(a(2:end,:)) a(1,:)])
bb = dataset([cell2mat(b(2:end,:)) b(1,:)])
cc = join(aa,bb, 'Keys',{'C'}, 'type','fullouter', 'MergeKeys',true)
with
cc =
A B C D
1 1 1 NaN
2 2 2 NaN
NaN NaN 3 3
NaN NaN 4 4