I have a cell array (2000*10) with each cell containing a string such as '25:20:55'.
I want to write a function that accepts 10 inputs (say '25:02:33', '58:69:88', '25:54:96', '48:58:36', '58:54:88' and so on) and looks for a match in each column corresponding to input value for that particular column (i.e. the first input data corresponds to 1st column, 2nd to 2nd column of the stored data and so on.
How can I write a function for the above comparison?
Assuming the cell array contains strings, you can find matches using strcmp:
input = {'25:02:33', '58:69:88', '25:54:96', '48:58:36', '58:54:88'};
match_idx = strcmp(repmat(input, size(cell_data,1),1), cell_data);
If you only want to know if there are matches in the respective columns at all and do not care about the line index of the match, you can do
match = any(match_idx,1);
Use ismember
ismember(your_var, your_cell);
e.g.
c = {'a', 'b', 'c', 'd'};
ismember('b', c)
ans =
1
ismember('q', c)
ans =
0
In your case, something like could work
function arr = myfun(inputvec, inputmat)
for i=1:length(inputvec) %// where inputvec is the cell-vector with the strings you want to search for
arr(i) = ismember(inputvec{i}, inputmat{:,i});
end
Related
What is the most efficient way to generate a table from 2 cell arrays. Array A contains data and Array B contains the corresponding names. I would like to combine them into a convenient table structure.
Cell_Array_A =
{[10x10],[10x10],[];
[10x11],[],[10x12];
[9x10],[13x10],[]}
Cell_Array_B =
{['A','B',[];
'B',[],'A';
'B','A',[]}
It should generate a table with the headers 'A' and 'B'. However, in my real data set, I have a lot of variable names, which I don't know. So I need a way to read all variables from the first row and use them to create the table for the rest of the matrix.
Example of the desired output:
'A' 'B'
[10x10] [10x10]
[10x12] [10x11]
[13x10] [9x10]
I tried so far to process the arrays row wise to get rid of the empty arrays. However this is not very efficient. I run the following code for each row in Array A and B. Below an example for the first row in Array A which I later on use as the tablet for my table.
order_row = {};
order_row = Cell_Array_A(1,:);
ordered_filenames = order_row(~cellfun('isempty',order_row));
Edited answer The idea is 1) to collect the non-empty column headers, 2) for each unique column header collect the corresponding values:
% Unique variable names
nul_names = cellfun(#isempty,Cell_Array_B);
var_names = unique(Cell_Array_B(~nul_names));
% Function to find a column header index
ixhead = #(h,c) cellfun(#(x) isequaln(x,h), c(:));
% Collect the values
var_values = cellfun( ...
#(h) Cell_Array_A(ixhead(h, Cell_Array_B)), var_names, ...
'UniformOutput', false ...
);
% Create the table
tbl = table(var_values{:}, 'VariableNames', var_names);
I'm a bit new to the matlab world, and I'm running into an issue that I'm sure has an easy solution.
I've imported some data from a text file and parsed out the headers, which resulted in a 1x35 cell called Data. In each cell (for example Data{1,1,1}) is data that looks like:
'600000 -947.772827 -107.045776 -70.818062'
'600001 -920.431396 -86.098122 -56.485119'
'600002 -878.332886 -88.673630 -85.249130'
'600003 -851.637695 -68.546539 -96.691711'
'600004 -834.707642 -28.951260 -73.218872'
'600005 -783.431580 40.657402 24.242268'
The problem is, each line is contained in a single column. I'd like to parse it out so that I have 4 columns instead of one.
I tried parsing out the Data cell even further using:
textscan(Data{1,1,1}, '%u%f10%f10%f10', 1)
But it resulted in the following error:
Error using textscan
First input must be of type double or string.
Can I use textscan this way, or do I need to use some other method to break out the text?
With textscan, you can only specify a single string or a single number. With your input, I suspect it is a 6 x 1 cell array of strings. As such, you have no choice but to iterate over each cell and convert each cell array contents with textscan Also, get rid of the %10 spacing as it's actually screwing up where you're parsing out the string. Also, set the identifier to identify the first number you see to double (%f) as opposed to unsigned integer (%u) to allow for easier conversion.
Therefore, do something like this:
>> Data{1,1,1} = {'600000 -947.772827 -107.045776 -70.818062'
'600001 -920.431396 -86.098122 -56.485119'
'600002 -878.332886 -88.673630 -85.249130'
'600003 -851.637695 -68.546539 -96.691711'
'600004 -834.707642 -28.951260 -73.218872'
'600005 -783.431580 40.657402 24.242268'};
>> format long g;
>> vals = cell2mat(cellfun(#(x) cell2mat(textscan(x, '%f%f%f%f', 1)), Data{1,1,1}, 'uni', 0))
vals =
Columns 1 through 3
600000 -947.772827 -107.045776
600001 -920.431396 -86.098122
600002 -878.332886 -88.67363
600003 -851.637695 -68.546539
600004 -834.707642 -28.95126
600005 -783.43158 40.657402
Column 4
-70.818062
-56.485119
-85.24913
-96.691711
-73.218872
24.242268
That statement vals = ... is quite a mouthful, but easy to explain. Start with this statement:
cell2mat(textscan(x, '%f%f%f%f', 1))
For a given cell x in Data{1,1,1}, we want to parse out four numbers for each string that is stored in x. textscan will place these numbers as individual cell elements into a cell array. We want to convert each element into a numeric array, and so cell2mat is required for us to do so.
In order to operate over all of the elements in Data{1,1,1}, we need to use cellfun to allow us to do so:
cellfun(#(x) cell2mat(textscan(x, '%f%f%f%f', 1)), Data{1,1,1}, 'uni', 0)
The first input is a function that operates on each cell stored in Data{1,1,1} (the second input). We are basically telling cellfun that we want to operate on each cell in the cell array stored in Data{1,1,1} in the way I talked about before. This function has input parameter x, which is one cell from Data{1,1,1}. Now, the uni flag is set to 0 because the output of cellfun will not be a single number, but an array of numbers - one array per line that you have in your cell array. The output of this stage would be a 6 element cell array where each location is a 4 element numeric array. To finish it off, we call cell2mat on this output to finally convert our text into a 2D matrix and therefore:
vals = cell2mat(cellfun(#(x) cell2mat(textscan(x, '%f%f%f%f', 1)), Data{1,1,1}, 'uni', 0))
format long g allows for better display formatting so we can see both the dominant number as well as the floating point numbers neatly.
Imagine a function with a variable number of input arguments, alternately asking for a string and a value.
myfunction('string1',value1,'string2',value2,...)
e.g.
myfunction('A',5,'B',10)
I want to keep the ability to call the function like that and I dont want to change the evaluation of varargin inside the function. (Except ('string1','string2',...,value1,value2,...) if that helps)
But I also have my input strings and values stored in a cell array inputvar <4x1 cell>:
inputvar =
'A' [5] 'B' [10]
Also this cell array has a variable length.
My intention is to call my function somehow as follows:
myfunction( inputvar )
which is obviously not working. Any ideas how I could transform my cell to a valid input syntax?
I already tried to generate a string like
''string1',value1,'string2',value2'
and use eval to use it in the function call. But it didn't worked out. So alternatively is there a way to transfor a string to code?
You should be able to do it like this:
myfunction(inputvar{:})
{:} creates a comma separated list
EDIT:
For example:
function val = myfunction(string1,value1,string2,value2)
if string1 == 'A'
val = value1;
else
val = value2;
end
myfunction('A',5,'B',10)
myfunction('B',5,'B',10)
A = {'A',5,'B',10};
myfunction(A{:})
A = {'B',5,'B',10};
myfunction(A{:})
returns:
ans = 5
ans = 10
ans = 5
ans = 10
I am trying to compare two cell arrays, 1x160 (a) and 80x1(b). My cell arrays consist of cells which have a number of strings inside. I wanna compare each string ans see if they are equal, then if they are equal, insert to new array, or insert 0 otherwise. I can't find any function for that. I tried 'isequal','strfind' and others. All of them give me next error message:
If any of the input arguments are cell arrays, the first must be a
cell array of strings and the second must be a character array.
Here is my code!
function [inter]=Intersect2(a,b)
int=cell(0);
b2=[b;b];
for i=1:length(a)
if a{i,1}==b2{i,1}(1) ( or 'isequal','strfind')
int{i}=a{i};
else
int{i}=0;
end
end
There are many ways to compare character arrays, one of which is strcmp.
We'll use cellfun as well to avoid looping.
a = {'Dude', 'I', 'am', 'a', 'moose'};
b = {'Well', 'I', 'am', 'a', 'mouse'};
index = cellfun(#strcmp, a, b);
This will compare each element of a against the corresponding element in b, returning a logical array index that is 1 when the elements match and 0 when they do not.
Use this to assign matching values:
int = cell(1, length(a));
int(index) = a(index);
int =
[] 'I' 'am' 'a' []
You can extend this concept to find the set intersection if you wish.
My question is easily summarized as: "Why does the following not work?"
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for i=1:numel(fields)
fields(i)
teststruct.(fields(i))
end
output:
ans = 'a'
??? Argument to dynamic structure reference must evaluate to a valid field name.
Especially since teststruct.('a') does work. And fields(i) prints out ans = 'a'.
I can't get my head around it.
You have to use curly braces ({}) to access fields, since the fieldnames function returns a cell array of strings:
for i = 1:numel(fields)
teststruct.(fields{i})
end
Using parentheses to access data in your cell array will just return another cell array, which is displayed differently from a character array:
>> fields(1) % Get the first cell of the cell array
ans =
'a' % This is how the 1-element cell array is displayed
>> fields{1} % Get the contents of the first cell of the cell array
ans =
a % This is how the single character is displayed
Since fields or fns are cell arrays, you have to index with curly brackets {} in order to access the contents of the cell, i.e. the string.
Note that instead of looping over a number, you can also loop over fields directly, making use of a neat Matlab features that lets you loop through any array. The iteration variable takes on the value of each column of the array.
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for fn=fields'
fn
%# since fn is a 1-by-1 cell array, you still need to index into it, unfortunately
teststruct.(fn{1})
end
Your fns is a cellstr array. You need to index in to it with {} instead of () to get the single string out as char.
fns{i}
teststruct.(fns{i})
Indexing in to it with () returns a 1-long cellstr array, which isn't the same format as the char array that the ".(name)" dynamic field reference wants. The formatting, especially in the display output, can be confusing. To see the difference, try this.
name_as_char = 'a'
name_as_cellstr = {'a'}
You can use the for each toolbox from http://www.mathworks.com/matlabcentral/fileexchange/48729-for-each.
>> signal
signal =
sin: {{1x1x25 cell} {1x1x25 cell}}
cos: {{1x1x25 cell} {1x1x25 cell}}
>> each(fieldnames(signal))
ans =
CellIterator with properties:
NumberOfIterations: 2.0000e+000
Usage:
for bridge = each(fieldnames(signal))
signal.(bridge) = rand(10);
end
I like it very much. Credit of course go to Jeremy Hughes who developed the toolbox.