I am trying to figure out how to get the column index when given the 2 row values in a 2-row cell array.
I don't know why I am having difficulty figuring this out because you can easily was find for 1 column value.
For example, give the cell array below:
{1,1,1,2,2,2;'apple','banana','orange','apple','banana','orange'}.'
I want to find where column1 = 2, and column2 = 'banana'
The output should be 5.
How would I do this?
I'll assume a cell array, according to #LuisMendo
cellarray = {1,1,1,2,2,2;'apple','banana','orange','apple','banana','orange'}.';
values = cell2mat(cellarray(:,1));
tmp1 = values == 1;
tmp2 = strcmp('banana', cellarray(:,2));
tmp3 = tmp1+tmp2;
result = find(tmp3 == 2);
This will get the values from the cell array, then searches for all values equal to 1. Then it uses strcmp to find all matches with 'banana' and adds that result to the logical array obtained by value. Finally it searches for where both instances are true, i.e. where tmp3 equals 2.
Whoohoo! My first golfed one liner. 59, 51 bytes!
find(((([A{:,1}])==1)'+strcmp('banana',A(:,2)))==2)
=
2
If you are into code-golfing -
find([A{1,:}]==2 & ismember(A(2,:),'banana'))
Sample run -
>> A
A =
[ 1] [ 1] [ 1] [ 2] [ 2] [ 2]
'apple' 'banana' 'orange' 'apple' 'banana' 'orange'
>> find([A{1,:}]==2 & ismember(A(2,:),'banana'))
ans =
5
Related
I have a cell array which contains some descriptions, namely my_des.
my_des = [{'FRD'} {'1'}; {'UNFRD'} {'2'}; {'OTH'} {'3'};];
I also have an approximately 5000x1 cell array. The elements in this array are either 'FRD', 'UNFRD' or 'OTH'.
What I want to do is replace these text values with the corresponding numeric values in my_des.
Currently my only idea (which I think isn't that great) is to loop through my_des and do a string replacement.
Example:
So say my current vector looks like this:
FRD
FRD
OTH
UNFRD
OTH
FRD
Then my desired output would be this:
1
1
3
2
3
1
The numbers come from the my_des array
Do you want to use the characters '1', '2', '3' or just the numbers 1, 2, 3? The distinction is the difference between a 1 line answer and a 2 line answer!
Based on your example, let's use the following data:
arr = {'FRD'; 'FRD'; 'OTH'; 'UNFRD'; 'OTH'; 'FRD'};
Get the row index within my_des of each element in arr, and use that to get the corresponding 2nd column values...
% If you just want the *number* then this is all you need
[~, idx] = ismember(arr, my_des);
% idx is the row within column 1 of my_des where the value in arr is found
% >> idx = [1; 1; 3; 2; 3; 1]
% If you want to get the values my_des then use idx as a row index
out = mydes(idx, 2);
% out is the corresponding values from the 2nd column of my_des, whatever they may be.
% >> out = {'1'; '1'; '3'; '2'; '3'; '1'};
Aside: why are you declaring a cell array by concatenating 1-element cell arrays for my_des? Instead, you can just do this:
my_des = {'FRD', '1';
'UNFRD', '2';
'OTH', '3'};
Suppose I have a cell of arrays of the same size, for example
arr = {[1 NaN 2 ], ...
[NaN 4 7 ], ...
[3 4 NaN] };
and I also have a vector, for example
vec = [1 2 2];
How do I find the corresponding cell entry that matches the vector vec. Matching means the entries in the same location are the same, except for NaNs?
For this particular vector vec I would like to have 1 returned, since it matches the first row.
Another vector [5 4 7] would return 2.
Vectors that don't match like [7 7 7] and vectors that match more than one entry like [3 4 7] should throw an error.
Note that the vector [3 7 4] does not match the second entry, because the order is important.
For each cell element, just check if
all(isnan(cellElement) | cellElement == vec)
is true, which means, you found a match. If you convert your cell to a matrix checkMatrix with multiple rows and each row corresponding to one cellElement, you can even do it without implementing a loop by repeating vec vertically and comparing the whole matrix in a single step. You will have to tell all() to check along dimension 2 rather than dimension 1 and have find() detect all the matches, like so:
find( all( ...
isnan(checkMatrix) | checkMatrix == repmat(vec,size(checkMatrix, 1),1) ...
, 2)); % all() along dimension 2
So I thought about it and came up with this:
matching_ind = #(x, arr) find(...
cellfun(#(y) max(abs(not(x-y==0).*not(isnan(x-y)))),...
arr) == 0);
inds = matching_ind(vec, arr);
if length(inds) ~= 1
error('42');
end
See if this bsxfun based approach works for you -
A = vertcat(arr{:});
matching_ind = find(all(bsxfun(#eq,A,vec(:).') | isnan(A),2)) %//'
if numel(matching_ind)~=1
error('Error ID : 42.')
else
out = matching_ind(1);
end
So in 3 X 18 cell array, 7 columns are empty and I need a new cell array that's 3 X 11. Any suggestions without going for looping ?
Let's consider the following cell array. Its second column consists only of [], so it should be removed.
>> c = {1 , [], 'a'; 2, [], []; 3, [], 'bc'}
c =
[1] [] 'a'
[2] [] []
[3] [] 'bc'
You can compute a logical index to tell which columns should be kept and then use it to obtain the result:
>> keep = any(~cellfun('isempty',c), 1); %// keep columns that don't only contain []
keep =
1 0 1 %// column 2 should be removed
>> result = c(:,keep)
result =
[1] 'a'
[2] []
[3] 'bc'
How it works:
cellfun('isempty' ,c) is a matrix the same size as c. It contains 1 at entry (m,n) if and only if c{m,n} is empty.
~cellfun('isempty' ,c) is the logical negation of the above, so it contains 1 where c is not empty.
any(~cellfun('isempty' ,c), 1) applies any to each column of the above. So it's a row vector such that its m-th entry equals 1 if any of the cells of c in that column are non-empty, and 0 otherwise.
The above is used as a logical index to select the desired columns of c.
Use cellfun to detect elements, then from that find columns with empty elements and delete those:
cellarray(:, any(cellfun(#isempty, cellarray), 1)) = [];
If instead you'd like to keep columns with at least one non-empty element, use all instead of any.
For example:
>> cellarray = {1 2 ,[], 4;[], 5, [], 3}
[1] [2] [] [4]
[] [5] [] [3]
>> cellarray(:,any(cellfun(#isempty, cellarray), 1))=[]
cellarray =
[2] [4]
[5] [3]
I've got 2 string cell arrays, one is the unique version of the other. I would like to count the number of occurrence of each values in the unique cell array given the other cell array. I got a large cell array so I thought I'd try my best to find answers to a more faster approach as oppose to looping...
An example:
x = {'the'
'the'
'aaa'
'b'
'the'
'c'
'c'
'd'
'aaa'}
y=unique(x)
I am looking for an output in any form that contains something like the following:
'aaa' = 2
'b' = 1
'c' = 2
'd' = 1
'the' = 3
Any ideas?
One way is to count the indices unique finds:
[y, ~, idx] = unique(x);
counts = histc(idx, 1:length(y));
which gives
counts =
2
1
2
1
3
in the same order as y.
histc is my default fallback for counting things, but the function I always forget about is probably better in this case:
counts = accumarray(idx, 1);
should give the same result and is probably more efficient.
I want to calculate the number of rows in a Cell array in MATLAB.
I use the code below to count the number of columns in a cell array but I do not know its way for counting the rows.
filledCells = ~cellfun(#isempty,a);
columns = sum(filledCells,2)
As an example, i've got x as a cell array:
x = [5] [1x8 double] [5]
This cell array has one row and three columns. I need a code to calculate the number of rows equal to "1" , but I did not find a way to calculate it.
I used most of ideas but it did not work then with the help of what herohuyongtao said i reach to this idea which worked properly
[nr,nc]=size(x)
Which nr is the number of rows
thanks all of you.
A slightly more general approach: works for rows or columns, and takes into account the size of each cell:
dim = 1; %// 1 for rows, 2 for columns
result = sum(cellfun(#(c) size(c,dim), a), dim);
Example:
>> a = {1, [2 3], []; 4, [], 5}
a =
[1] [1x2 double] []
[4] [] [5]
>> dim = 1;
gives
>> result = sum(cellfun(#(c) size(c,dim), a), dim)
result =
2 1 1
Try
%% "a" is the cell array, total num of rows will be saved in "rows"
num = length(a); % num of objects in "a" - big rows
rows = 0;
for i=1:num
[r c] = size(C{i})
rows = rows+r;
end
The simplest way to achieve this would be to get the first dimension of the size.
rowCount = size(x,1)