cell string array manipulation - matlab

I have a cell with strings in the following format:
data = {'para1_left = numeric value';'para1_right = numeric value';
'para2_left = numeric value';'para2_right = numeric value';
........
'para100_up = numeric value';'para100_down = numeric value';
and so on...I have a few hundreds of these};
I want two cells out of this cell: one with just the parameter names, p_name, and another with just the values, p_val.
Once I have the two cells, I want to compare the p_name cell with another cell of shorter length. This new cell will have strings in the following format:
new_cell = {'para1';'para5';'para10';...'para25'};
Basically these strings miss the trailing parts: _left, _right, etc.
Then, I want to have a list of indices of p_name that contain any of the strings in new_cell, indx_match = [1;2;10;20....and so on] so that I can get the values of the matching parameter names by doing p_val{indx_match}.
I want to do the above with the minimum number of lines, probably using cellfun. I figured out how to find the indices by using strfind command, but then it creates a cell array and p_val{indx_match} doesn't work (I tried various ways using cellfun, but no success yet).

I'm not sure exactly what you want, but this should get you on the right track.
Org = {'a_l = 5'; 'a_r = 7'; 'b_l = 6'; 'b_r = 7'};
Shr = {'a'};
splt = cellfun(#(s) strsplit(s, {'=', ' '}), Org, 'uni', 0);
p_name = cellfun(#(c) c{1}, splt, 'uni', 0);
p_val = cellfun(#(c) str2num(c{2}), splt);
param = cellfun(#(c) strsplit(c, '_'), p_name, 'uni', 0);
param = cellfun(#(c) c{1}, param, 'uni', 0);
index = cellfun(#(s) strfind(param, s), Shr, 'uni', 0);

Related

How to delete a range of rows from a cell array using cellfun, matlab

I have a 1x3 cell with
timepositionrawdata = {time, lat, lon};
% Extract every fourth instance of the raw data
time = timepositionrawdata{1,1}(1:4:end);
lat = timepositionrawdata{1,2}(1:4:end);
lon = timepositionrawdata{1,3}(1:4:end);
timepositionrawdata = {time, lat, lon};
% Delete and add appropriate rows to match image sequence times
timepositionrawdata{1}(278,:) = [];
timepositionrawdata{2}(278,:) = [];
timepositionrawdata{3}(278,:) = [];
timepositionrawdata = timepositionrawdata{1}([1:281, 281:end],:);
timepositionrawdata = timepositionrawdata{2}([1:281, 281:end],:);
timepositionrawdata = timepositionrawdata{3}([1:281, 281:end],:);
I would like to be able to delete particular rows in the whole cell. How do you use cellfun to do this?
You first need to write a function that processes one cell correctly, then use cellfun to apply it to the cell array.
function time = process_one_cell(time)
time = time(1:4:end);
time(278, :) = [];
time = time([1:281, 281:end], :); % I'm not sure why you're doing this, looks kind of pointless.
end
And then call the function as follows
timepositionrawdata = cellfun(#process_one_cell, timepositionrawdata, 'UniformOutput', 0);
% or if you prefer to be more verbose
timepositionrawdata = cellfun(#(x) process_one_cell(x), timepositionrawdata, 'UniformOutput', 0);

Matlab loop through functions using an array in a for loop

I am writing a code to do some very simple descriptive statistics, but I found myself being very repetitive with my syntax.
I know there's a way to shorten this code and make it more elegant and time efficient with something like a for-loop, but I am not quite keen enough in coding (yet) to know how to do this...
I have three variables, or groups (All data, condition 1, and condition 2). I also have 8 matlab functions that I need to perform on each of the three groups (e.g mean, median). I am saving all of the data in a table where each column corresponds to one of the functions (e.g. mean) and each row is that function performed on the correspnding group (e.g. (1,1) is mean of 'all data', (2,1) is mean of 'cond 1', and (3,1) is mean of 'cond 2'). It is important to preserve this structure as I am outputting to a csv file that I can open in excel. The columns, again, are labeled according the function, and the rows are ordered by 1) all data 2) cond 1, and 3) cond 2.
The data I am working with is in the second column of these matrices, by the way.
So here is the tedious way I am accomplishing this:
x = cell(3,8);
x{1,1} = mean(alldata(:,2));
x{2,1} = mean(cond1data(:,2));
x{3,1} = mean(cond2data(:,2));
x{1,2} = median(alldata(:,2));
x{2,2} = median(cond1data(:,2));
x{3,2} = median(cond2data(:,2));
x{1,3} = std(alldata(:,2));
x{2,3} = std(cond1data(:,2));
x{3,3} = std(cond2data(:,2));
x{1,4} = var(alldata(:,2)); % variance
x{2,4} = var(cond1data(:,2));
x{3,4} = var(cond2data(:,2));
x{1,5} = range(alldata(:,2));
x{2,5} = range(cond1data(:,2));
x{3,5} = range(cond2data(:,2));
x{1,6} = iqr(alldata(:,2)); % inter quartile range
x{2,6} = iqr(cond1data(:,2));
x{3,6} = iqr(cond2data(:,2));
x{1,7} = skewness(alldata(:,2));
x{2,7} = skewness(cond1data(:,2));
x{3,7} = skewness(cond2data(:,2));
x{1,8} = kurtosis(alldata(:,2));
x{2,8} = kurtosis(cond1data(:,2));
x{3,8} = kurtosis(cond2data(:,2));
% write output to .csv file using cell to table conversion
T = cell2table(x, 'VariableNames',{'mean', 'median', 'stddev', 'variance', 'range', 'IQR', 'skewness', 'kurtosis'});
writetable(T,'descriptivestats.csv')
I know there is a way to loop through this stuff and get the same output in a much shorter code. I tried to write a for-loop but I am just confusing myself and not sure how to do this. I'll include it anyway so maybe you can get an idea of what I'm trying to do.
x = cell(3,8);
data = [alldata, cond2data, cond2data];
dfunction = ['mean', 'median', 'std', 'var', 'range', 'iqr', 'skewness', 'kurtosis'];
for i = 1:8,
for y = 1:3
x{y,i} = dfucntion(i)(data(1)(:,2));
x{y+1,i} = dfunction(i)(data(2)(:,2));
x{y+2,i} = dfunction(i)(data(3)(:,2));
end
end
T = cell2table(x, 'VariableNames',{'mean', 'median', 'stddev', 'variance', 'range', 'IQR', 'skewness', 'kurtosis'});
writetable(T,'descriptivestats.csv')
Any ideas on how to make this work??
You want to use a cell array of function handles. The easiest way to do that is to use the # operator, as in
dfunctions = {#mean, #median, #std, #var, #range, #iqr, #skewness, #kurtosis};
Also, you want to combine your three data variables into one variable, to make it easier to iterate over them. There are two choices I can see. If your data variables are all M-by-2 in dimension, you could concatenate them into a M-by-2-by-3 three-dimensional array. You could do that with
data = cat(3, alldata, cond1data, cond2data);
The indexing expression into data that retrieves the values you want would be data(:, 2, y). That said, I think this approach would have to copy a lot of data around and probably isn't the best for performance. The other way to combine data together is in 1-by-3 cell array, like this:
data = {alldata, cond1data, cond2data};
The indexing expression into data that retrieves the values you want in this case would be data{y}(:, 2).
Since you are looping from y == 1 to y == 3, you only need one line in your inner loop body, not three.
for y = 1:3
x{y, i} = dfunctions{i}(data{y}(:,2));
end
Finally, to get the cell array of strings containing function names to pass to cell2table, you can use cellfun to apply func2str to each element of dfunctions:
funcnames = cellfun(#func2str, dfunctions, 'UniformOutput', false);
The final version looks like this:
dfunctions = {#mean, #median, #std, #var, #range, #iqr, #skewness, #kurtosis};
data = {alldata, cond1data, cond2data};
x = cell(length(data), length(dfunctions));
for i = 1:length(dfunctions)
for y = 1:length(data)
x{y, i} = dfunctions{i}(data{y}(:,2));
end
end
funcnames = cellfun(#func2str, dfunctions, 'UniformOutput', false);
T = cell2table(x, 'VariableNames', funcnames);
writetable(T,'descriptivestats.csv');
You can create a cell array of functions using str2func :
function_string = {'mean', 'median', 'std', 'var', 'range', 'iqr', 'skewness', 'kurtosis'};
dfunction = {};
for ii = 1:length(function_string)
fun{ii} = str2func(function_string{ii})
end
Then you can use it on your data as you'd like to :
for ii = 1:8,
for y = 1:3
x{y,i} = dfucntion{ii}(data(1)(:,2));
x{y+1,i} = dfunction{ii}(data(2)(:,2));
x{y+2,i} = dfunction{ii}(data(3)(:,2));
end
end

Stripping suffix from all elements of string cell array

I have a cell array containing strings, called old_array. Each element ends with the suffix '.dat'. I want to create a new cell array, called new_array, that has the same elements, but without this suffix.
I know that the following function exists:
[new_array] = arrayfun(func, old_array)
But what do I use for func? I thought about using strsplit(str, '.') and taking the first element of this array, something like:
[new_array] = arrayfun(strsplit(*, '.')[0], old_array)
But what do I place instead of the *? What's the best solution?
If every element in your array ends with .dat, why don't you simply extract all of the characters except the last 4 for each string in your cell array?
new_array = cellfun(#(x) x(1:end-4), old_array, 'UniformOutput', false);
This should return a new cell array stored in new_array where each element loses the last 4 characters of each string from the cell array old_array, which is the string .dat for each string in old_array.
However, if you want to make this more robust and if you want to accommodate any file name, you can use strsplit like what you have in your post. You would have to structure it like so:
%// Use to split up the strings for each cell and store in individual cells
new_array_temp = cellfun(#(x) strsplit(x, '.'), old_array, 'UniformOutput', false);
%// Extract the first cell of each nested cell
new_array = cellfun(#(x) x{1}, new_array_temp, 'UniformOutput', false);
We need to do the first step so that we can return a cell array of cells. Each nested cell within the larger cell array will contain strings that are delimited by . within the nested cell element. You then run the next command so that we extract the first string of each nested cell, which is the file name itself before the ..
Here's an example that shows you how this is run, as well as the intermediate outputs:
old_array = {'Hi.dat', 'how.dat', 'are.dat', 'you.dat'};
new_array_temp = cellfun(#(x) strsplit(x, '.'), old_array, 'UniformOutput', false);
celldisp(new_array_temp);
new_array_temp{1}{1} =
Hi
new_array_temp{1}{2} =
dat
new_array_temp{2}{1} =
how
new_array_temp{2}{2} =
dat
new_array_temp{3}{1} =
are
new_array_temp{3}{2} =
dat
new_array_temp{4}{1} =
you
new_array_temp{4}{2} =
dat
new_array = cellfun(#(x) x{1}, new_array_temp, 'UniformOutput', false);
disp(new_array);
'Hi' 'how' 'are' 'you'
Minor note
Note: strsplit only works for MATLAB R2013a and up. If you want this to work with previous versions of MATLAB, use regexp. Replace the strsplit call within cellfun with this:
new_array_temp = cellfun(#(x) regexp(x, '\.', 'split'), 'UniformOutput', false);
This should basically achieve the same thing as strsplit. However, if you really, really, really, really want to use strsplit, there is an implementation on the MathWorks File Exchange: http://www.mathworks.com/matlabcentral/fileexchange/21710-string-toolkits/content/strings/strsplit.m

Write field name and value form structures to a file

I am wondering how can I write a full structure in an output file *.txt with all fieldnames and the respectives values. For example
allvariables=
names='raw.txt'
date= = '**/**/2013'
User = Mr/Mrs *
timeProcessing = 20
numberIterations = 1000;
Should be written in output.txt with all the information displayed before.
This is just an example but my structure has a length of 50 fieldnames, so I would appreciate any suggestion!
Here's something you can use:
%// Extract field data
fields = fieldnames(allvariables);
values = struct2cell(allvariables);
%// Optional: add enclosing apostrophes around string values
idx = cellfun(#ischar, values);
values(idx) = cellfun(#(x){['''', x, '''']}, values(idx));
%// Convert numerical values to strings
idx = cellfun(#isnumeric, values);
values(idx) = cellfun(#num2str, values(idx), 'UniformOutput', false);
%// Convert cell arrays of strings to comma-delimited strings
idx = cellfun(#iscellstr, values);
stringify_cellstr = #(x){['{' sprintf('''%s'', ', x{1:end - 1}) ...
sprintf('''%s''', x{end}) '}']};
values(idx) = cellfun(stringify_cellstr, values(idx));
%// Convert cell array of numbers to strings
idx = cellfun(#iscell, values);
isnumber = #(x)isnumeric(x) && isscalar(x);
idx_num = cellfun(#(x)all(arrayfun(#(k)isnumber(x{k}),1:numel(x))), values(idx));
idx(idx) = idx_num;
stringify_cellnum = #(x){['{' sprintf('%d, ' x{1:end - 1}) num2str(x{end}) '}']};
values(idx) = cellfun(stringify_cellnum, values(idx));
%// Combine field names and values in the same array
C = {fields{:}; values{:}};
%// Write fields to text file
fid = fopen('output.txt', 'wt');
fprintf(fid, repmat('%s = %s\n', 1, size(C, 2)), C{:});
fclose(fid);
This solution is essentially a variant of this one. Note that it assumes that each field contains a scalar value or a string, but it can be extended to handle other types, of course.
EDIT: added handling for fields storing cell arrays of strings and cell arrays of numbers.

Merge Matrix and Cell array of strings

I'm looking to export data to excel from Matlab in the form of
ColName Value
======= ======
Col1 Val1
Col2 Val2
I have my ColName in colheaders which is a 1xM cell (of strings) and my values in predRes which is a 1xM Matrix (of double).
I've tried to combine the two into a single structure with the below code which doesn't work, giving me ??? Conversion to cell from double is not possible.
out = cell(size(X,2),2);
out(:,1) = colheaders(2:end)';
out(:,2) = predRes';
functions like mat2str seem to merge the input into a single string, which isn't the right thing here.
Any ideas?
I am not sure what you are trying to do.
If you want to save to Excel, you may mean this:
colheaders = {'aa','b','ccc'};
predRes = [1,2,3];
out = [colheaders', mat2cell(predRes',ones(3,1),1)];
s = xlswrite('tempdata.xls', out);
If you want to concatenate numbers to strings:
colheaders = {'aa','b','ccc'};
predRes = [1,2,3];
out = strcat(colheaders', num2str(predRes'))