Array intersection issue (Matlab) - arrays

I am trying to carry out the intersection of two arrays in Matlab but I cannot find the way.
The arrays that I want to intersect are:
and
I have tried:[dur, itimes, inewtimes ] = intersect(array2,char(array1));
but no luck.
However, if I try to intersect array1 with array3 (see array3 below), [dur, itimes, inewtimes ] = intersect(array3,char(array1));the intersection is performed without any error.
Why I cannot intersect array1 with array2?, how could I do it?. Thank you.

Just for ease of reading, your formats for Arrays are different, and you want to make them the same. There are many options for you, like #Visser suggested, you could convert the date/time into a long int which allows faster computation, or you can keep them as strings, or even convert them into characters (like what you have done with char(Array2)).
This is my example:
A = {'00:00:00';'00:01:01'} %//Type is Cell String
Z = ['00:00:00';'00:01:01'] %//Type is Cell Char
Q = {{'00:00:00'};{'00:01:01'}} %//Type is a Cell of Cells
A = cellstr(A) %//Convert CellStr to CellStr is essentially doing nothing
Z = cellstr(Z) %//Convert CellChar to CellStr
Q = vertcat(Q{:,:}) %// Convert Cell of Cells to Cell of Strings
I = intersect (A,Z)
>>'00:00:00'
'00:01:01'
II = intersect (A,Q)
>>'00:00:00'
'00:01:01'
This keeps your dates in the format of Strings in case you want to export them back into a txt/csv file.

Your first array would look something like this:
array1 = linspace(0,1,86400); % creates 86400 seconds in 1 day
Your second array should be converted using datenum, then use cell2mat to make it a matrix. Lastly, use ismember to find the intersection:
InterSect = ismember(array2,array1);

Related

matlab: logically comparing two cell arrays

I have an excel file from which I obtained two string arrays, Titles of dimension 6264x1 and another Names of dimension 45696x1. I want to create an output matrix of size 6264x45696 containing in the elements a 1 or 0, a 1 if Titles contains Names.
I think I want something along the lines of:
for (j in Names)
for (k in Titles)
if (Names[j] is in Titles[k])
write to excel
end
end
end
But I don't know what functions I should use to achieve what I have in the picture. Here is what I have come up with:
[~,Title] = xlsread('exp1.xlsx',1,'A3:A6266','basic');
[~,Name] = xlsread('exp1.xlsx',2,'B3:B45698','basic');
A = cellstr(Title);
GN = cellstr(Name);
BinaryMatrix = false(45696,6264);
for i=1:1:45696
for j=1:1:6264
if (~isempty(ismember(A,GN)))
BinaryMatrix(i,j)= true;
end
end
end
the problem with this code is that it never finishes running, although there are no suggestions within matlab.
You can use third output of unique to get numbers corresponding to each string element and use bsxfun to compare numbers.
GN = cellstr(Name);
A = cellstr(Title);
B = [ GN(:); A(:)];
[~,~,u]= unique(B);
BinaryaMatrix = bsxfun(#eq, u(1:numel(GN)),u(numel(GN)+1:end).');
ismember can handle cell arrays of character vectors. Its second output tells you the information you need, from which you can build the result using sparse (it could also be done by preallocating and using [sub2ind):
[~, m] = ismember(Titles, Names);
BinaryMatrix = full(sparse(nonzeros(m), find(m), true, numel(Names), numel(Titles)));

Split matrix into several depending on value in Matlab

I have a cell array that I need to split into several matrices so that I can take the sum of subsets of the data. This is a sample of what I have:
A = {'M00.300', '1644.07';...
'M00.300', '9745.42'; ...
'M00.300', '2232.88'; ...
'M00.600', '13180.82'; ...
'M00.600', '2755.19'; ...
'M00.600', '15800.38'; ...
'M00.900', '18088.11'; ...
'M00.900', '1666.61'};
I want the sum of the second columns for each of 'M00.300', 'M00.600', and 'M00.900'. For example, to correspond to 'M00.300' I would want 1644.07 + 9745.42 + 2232.88.
I don't want to just hard code it because each data set is different, so I need the code to work for different size cell arrays.
I'm not sure of the best way to do this, I was going to begin by looping through A and comparing the strings in the first column and creating matrices within that loop, but that sounded messy and not efficient.
Is there a simpler way to do this?
Classic use of accumarray. You would use the first column as an index and the second column as the values associated with each index. accumarray works where you group values that belong to the same index together and you apply a function to those values. In your case, you'd use the default behaviour and sum things together.
However, you'll need to convert the first column into numeric labels. The third output of unique will help you do this. You'll also need to convert the second column into a numeric array and so str2double is a perfect way to do this.
Without further ado:
[val,~,id] = unique(A(:,1)); %// Get unique values and indices
out = accumarray(id, str2double(A(:,2))); %// Aggregate the groups and sum
format long g; %// For better display of precision
T = table(val, out) %// Display on a nice table
I get this:
>> T = table(val, out)
T =
val out
_________ ________
'M00.300' 13622.37
'M00.600' 31736.39
'M00.900' 19754.72
The above uses the table class that is available from R2013b and onwards. If you don't have this, you can perhaps use a for loop and print out each cell and value separately:
for idx = 1 : numel(out)
fprintf('%s: %f\n', val{idx}, out(idx));
end
We get:
M00.300: 13622.370000
M00.600: 31736.390000
M00.900: 19754.720000

Matlab: Delete the item in an N-dimensional array whose Nth dimension is 1, where N is unknown?

I have an N-dimensional array of items whose last dimension is the index of the array.
For example, if the array A contained images, then A(:,:,:,1) would be the first image, A(:,:,:,2) would be the second image, and so forth.
Similarly, if the array just contained integers, then A(:,1) would be the first integer, A(:,2) would be the second integer, and so forth.
-=-=-=-
What I'm trying to do is delete the first item from A when I do not know ahead of time what dimensionality it is.
If A contains images, I want to do this:
A(:,:,:,1) = [];
If A contains integers, I want to do this:
A(:,1) = [];
The problem is since I don't know what dimensionality it is, I don't know how many colons to put, and I don't know how to denote "N-1 colons here" in Matlab.
I'm hoping there is a programmatic way to do this, but I frankly have no idea what to search for if this is possible.
You can either use cell to comma-separated list expansion:
%// Build cell: {':', ':', ..., ':', [1]}
I(1:ndims(A)-1) = {':'};
I{ndims(A)} = 1;
%// Expand cell to comma separated list and delete:
A(I{:}) = [];
Or convert to cell using num2cell and then convert back using cell2mat:
C = num2cell(A,1:ndims(A)-1);
A = cell2mat(C(2:end));
I guess that unless you really need n-dimensional arrays, doing this with a cell array of n-1 dimensional arrays instead (as is C in the above code) should be a smart move in terms of simplicity of notation.

How to permute the arrays within a cell array without using loops

I have a two arrays within a <1x2 cell>. I want to permute those arrays. Of course, I could use a loop to permute each one, but is there any way to do that task at once, without using loops?
Example:
>> whos('M')
Name Size Bytes Class Attributes
M 1x2 9624 cell
>> permute(M,p_matrix)
This does not permute the contents of the two arrays within M.
I could use something like:
>> for k=1:size(M,2), M{k} = permute(M{k},p_matrix); end
but I'd prefer not to use loops.
Thanks.
This seems to work -
num_cells = numel(M) %// Number of cells in input cell array
size_cell = size(M{1}) %// Get sizes
%// Get size of the numeric array that will hold all of the data from the
%// input cell array with the second dimension representing the index of
%// each cell from the input cell array
size_num_arr = [size_cell(1) num_cells size_cell(2:end)]
%// Dimensions array for permuting with the numeric array holding all data
perm_dim = [1 3:numel(size_cell)+1 2]
%// Store data from input M into a vertically concatenated numeric array
num_array = vertcat(M{:})
%// Reshape and permute the numeric array such that the index to be used
%// for indexing data from different cells ends up as the final dimension
num_array = permute(reshape(num_array,size_num_arr),perm_dim)
num_array = permute(num_array,[p_matrix numel(size_cell)+1])
%// Save the numeric array as a cell array with each block from
%// thus obtained numeric array from its first to the second last dimension
%// forming each cell
size_num_arr2 = size(num_array)
size_num_arr2c = num2cell(size_num_arr2(1:end-1))
M = squeeze(mat2cell(num_array,size_num_arr2c{:},ones(1,num_cells)))
Some quick tests show that mat2cell would prove to be the bottleneck, so if you don't mind indexing into the intermediate numeric array variable num_array and use it's last dimension for an equivalent indexing into M, then this approach could be useful.
Now, another approach if you would like to preserve the cell format would be with arrayfun, assuming each cell of M to be a 4D numeric array -
M = arrayfun(#(x) num_array(:,:,:,:,x),1:N,'Uniform',0)
This seems to perform much better than with mat2cell in terms of performance.
Please note that arrayfun isn't a vectorized solution as most certainly it uses loops behind-the-scenes and seems like mat2cell is using for loops inside its source code, so please do keep all these issues in mind.

Matlab cell array to string vector - unique

Going nuts with cell array, because I just can't get rid of it... However, it will be an easy one for you guys out here.
So here is why:
I have a dataset (data) which contains two variables: A (Numbers) and B (cell array).
Unfortunately I can't even reconstruct the problem nevertheless my imported table looks like this:
data=dataset;
data.A = [1;1;3;3;3];
data.B = ['A';'A';'BUU';'BUU';'A'];
where data.B is of the type 5x1 cell which I can't reconstruct
all I want now is the unique rows like
ans= [1 A;3 BUU;3 A]
the result should be in a dataset or just two vectors where the rows are equivalent.
but unique([dataA dataB],'rows') can't handle cell arrays and I can't find anywhere in the www how I simple convert the cell array B to a vector of strings (does it exist?).
cell2mat() didn't work for me, because of the different word length ('A' vs 'BUU').
Though, two things I would love to learn: Making an 5x1 cell to an string vector
and find unique rows out of numbers and strings (or cells).
Thank you very much!
Cheers Dominik
The problem is that the A and B fields are of a different type. Although they could be concatenated into a cell array, unique can't handle that. A general trick for cases like this is to "translate" elements of each field (column) to unique identifiers, i.e. numbers. This translation can be done applying unique to each field separately and getting its third output. The obtained identifiers can now be concatenated into a matrix, so that each row of this matrix is a "composite identifier". Finally, unique with 'rows' option can be applied to this matrix.
So, in your case:
[~, ~, kA] = unique(data.A);
[~, ~, kB] = unique(data.B);
[~, jR] = unique([kA kB], 'rows');
Now build the result as (same format as data)
result.A = data.A(jR);
result.B = data.B(jR);
or as (2D cell array)
result = cat(2, mat2cell(data.A(jR), ones(1,numel(jR))), data.B(jR));
Here is my clumpsy solution
tt.A = [1;1;3;3;3];
tt.B = {'A';'A';'BUU';'BUU';'A'};
Convert integers to characters, then merge and find unique strings
tt.C = cellstr(num2str(tt.A));
tt.D = cellfun(#(x,y) [x y],tt.C,tt.B,'UniformOutput',0);
[tt.F,tt.E] = unique(tt.D);
Display results
tt.F

Resources