MATLAB cell to string - excel

I am trying to read an excel sheet and then and find cells that are not empty and have date information in them by finding two '/' in a string
but matlab keeps to erroring on handling cell type
"Undefined operator '~=' for input arguments of type 'cell'."
"Undefined function 'string' for input arguments of type 'cell'."
"Undefined function 'char' for input arguments of type 'cell'."
MyFolderInfo = dir('C:\');
filename = 'Export.xls';
[num,txt,raw] = xlsread(filename,'A1:G200');
for i = 1:length(txt)
if ~isnan(raw(i,1))
if sum(ismember(char(raw(i,1)),'/')) == 2
A(i,1) = raw(i,1);
end
end
end
please help fixing it

There are multiple issues with your code. Since raw is a cell array, you can't run isnan on it, isnan is for numerical arrays. Since all you're interested in is cells with text in them, you don't need to use raw at all, any blank cells will not be present in txt.
My approach is to create a logical array, has_2_slashes, and then use it to extract the elements from raw that have two slashes in them.
Here is my code. I generalized it to read multiple columns since your original code only seemed to be written to handle one column.
filename = 'Export.xls';
[~, ~, raw] = xlsread(filename, 'A1:G200');
[num_rows, num_cols] = size(raw);
has_2_slashes = false(num_rows, num_cols);
for row = 1:num_rows
for col = 1:num_cols
has_2_slashes(row, col) = sum(ismember(raw{row, col}, '/')) == 2;
end
end
A = raw(has_2_slashes);

cellfun(#numel,strfind(txt,'/'))
should give you a numerical array where the (i,j)th element contains the number of slashes. For example,
>> cellfun(#numel,strfind({'a','b';'/','/abc/'},'/'))
ans =
0 0
1 2
The key here is to use strfind.
Now you may want to expand a bit in your question on what you intend to do next with txt -- in other words, specify desired output more, which is always a good thing to do. If you intend to read the dates, it may be better to just read it upfront, for example by using regexp or datetime as opposed to getting an array which can then map to where the dates are. As is, using ans>=2 next gives you the logical array that can let you extract the matched entries.

Related

How to assign multiple lines to a string variable in Matlab

I have a few lines of text like this:
abc
def
ghi
and I want to assign these multiple lines to a Matlab variable for further processing.
I am copying these from very large text file and want to process it in Matlab Instead of saving the text into a file and then reading line by line for processing.
I tried to handle the above text lines as single string but am getting an error whilst trying to assign to a variable:
x = 'abc
def
ghi'
Error:
x = 'abc
|
Error: String is not terminated properly.
Any suggestions which could help me understand and solve the issue will be highly appreciated.
I frequently do this, namely copy text from elsewhere which I want to hard-code into a MATLAB script (in my case it's generally SQL code I want to manipulate and call from MATLAB).
To achieve this I have a helper function in clipboard2cellstr.m defined as follows:
function clipboard2cellstr
str = clipboard('paste');
str = regexprep(str, '''', ''''''); % Double any single quotes
strs = regexp(str, '\s*\r?\n\r?', 'split');
cs = sprintf('{\n''%s''\n}', strjoin(strs, sprintf('''\n''')));
clipboard('copy', cs);
disp(cs)
disp('(Copied to Clipboard)')
end
I then copy the text using Ctrl-c (or however) and run clipboard2cellstr. This changes the contents of the clipboard to something I can paste into the MATLAB editor using Ctrl-v (or however).
For example, copying this line
and this line
and this one, and then running the function generates this:
{
'For example, copying this line'
'and this line'
'and this one, and then running the function generates this:'
}
which is valid MATLAB which can be pasted directly in.
Your error is because you ended the line when MATLAB was expecting a closing quote character. You must use array notation to have multi-line or multi-element arrays.
You can assign like this if you use array notation
x = ['abc'
'def'
'hij']
>> x = 3×3 char array
Note: with this method, your rows must have the same number of characters, as you are really dealing with a character array. You can think of a character array like a numeric matrix, hence why it must be "rectangular".
If you have MATLAB R2016b or newer, you can use the string data type. This uses double quotes "..." rather than single quotes '...', and can be multi-line. You must still use array notation:
x = ["abc"
"def"
"hijk"]
>> x = 3×1 string array
We can have different numbers of characters in each line, as this is simply a 3 element string array, not a character array.
Alternatively, use a cell array of character arrays (or strings)
x = {'abc'
'def'
'hijk'}
>> x = 3×1 cell array
Again, you can have character arrays or strings of different lengths within a cell array.
In all of the above examples, a newline is simply for readability and can be replaced by a semi-colon ; to denote the next line of the array.
The option you choose will depend on what you want to do with the text. If you're reading from a file, I would suggest the string array or the cell array, as they can deal with different length lines. For backwards compatibility, use a cell array. You may find cellfun relevant for operating on cell arrays. For native string operations, use a string array.

searching for strings in array of character/strings matlab

I have the following array:-
dir=['E','B','R']
I want to find the index of the elemen 'E'.
>> find(dir=='E')
ans =
1
But i want to do the same for an array of strings rather than array of characters like:
dir=['E','G','T','BR']
But there is an error to find 'BR'. I want the output to be 4.
>> find(dir=='BR')
Error using ==
Matrix dimensions must agree.
How to work-around this error?
I recommend you look at the documentation on string (char array) handling in matlab such as here.
What you want to do is work with cell arrays of strings:
dir = {'E','G','T','BR'}
find(ismember(dir,'BR'))
ans = 4

MATLAB: populate cell array and format number

What's the efficient way to populate a cell array with values from a vector (each formatted differently).
For example:
V = [12.3 .004 3 4.222];
Desired cell array:
array = {'A = 12.30' 'B = 0.004' 'C = 3' 'D = 4'};
Is there an easier way than calling sprintf for each and every cell?
array = {sprintf('A = %.2f',V(1)) sprintf('B = %.3f',V(2)) ... }
There's no vectorized form of sprintf that supports different formats, so you're mostly stuck with a sprintf call per cell. But you could arrange the code to be easier to deal with in a loop.
V = [12.3 .004 3 4.222];
names = num2cell('A':'Z');
formats = { '%.2f' '%.3f' '%d' '%.0f' };
c = cell(size(V));
for i = numel(V)
c{i} = sprintf(['%s = ' formats{i}], names{i}, V(i));
end
It would be tricky to get anything faster than the naive way without dropping down to Java or C, because it's still going to take a sprintf() call for each cell, and that's going to dominate the execution time.
If you have a large number of elements and a relatively small number of formats, you could use unique() to group them up in to one sprintf() call per format, using the vectorized version of sprintf and then splitting on a delimiter to get individual strings. That may or may not be faster, depending on your exact data set and implementation.
Or you could write a MEX file that pushes the loop down in to C, looping over a call to C's sprintf. That would be faster, once you get up to moderately large input sizes.
It can be done as follows:
V = [12.3 .004 3 4.222];
names = {'A', 'B', 'C', 'D'};
array = strcat(names(:), ' = ', ...
strtrim(mat2cell(num2str(V(:), '%.4f'), ones(1,numel(V))))).';
How this works:
num2str gives a char matrix, using a format specifier (you may want to change the one I used).
mat2cell converts that into a cell array, putting each row into a cell.
strtrim removes spaces.
strcat concatenates cell-wise.

Matlab: How do I compare two string arrays and then select out the number values associated with those strings?

I have one array of strings that I want to use to pull out samples from a larger matrix of data that I have. Right now I have the one array of strings, 1200x1. And my actual data 'names' (string array that denotes what the values correspond to 6855x1, and 'data' is 6855x2.
This is what I came up with:
C = intersect(names,sites) %To find common strings
%To find where these strings are in my original dataset:
Q=zeros(length(C),1)
for i=1:length(C)
for j=1
while strcmp(C(i),names(j))==0
j=j+1
Q(i)=j
end
end
end
%To then use the above values to compile a new vector with the actual data values from 'data':
A=zeros(length(Q),1)
for i=1:length(Q)
A(i) = mock(Q(i),1)
The only problem is I am running the second set of loops I listed right now, and it is obvious that it will take several hours. I think there must be a quicker way without setting up three loops. Does anyone know a better method?
The first thing to note is that your loop over Q can be trivially accelerated, as:
A = mock(Q,1);
although I suspect that you meant data(Q,2).
If you store your name list in a cell array rather than a regular array, you should be able to accelerate things further. Assume that data is a cell array, names{1:6855} and value list numbers(1:6855).
A = zeros(length(C),1);
for i1=1:length(C)
A(i1)=numbers(strcmp(C(i1),names));
end

MATLAB search cell array for string subset

I'm trying to find the locations where a substring occurs in a cell array in MATLAB. The code below works, but is rather ugly. It seems to me there should be an easier solution.
cellArray = [{'these'} 'are' 'some' 'nicewords' 'and' 'some' 'morewords'];
wordPlaces = cellfun(#length,strfind(cellArray,'words'));
wordPlaces = find(wordPlaces); % Word places is the locations.
cellArray(wordPlaces);
This is similar to, but not the same as this and this.
The thing to do is to encapsulate this idea as a function. Either inline:
substrmatch = #(x,y) ~cellfun(#isempty,strfind(y,x))
findmatching = #(x,y) y(substrmatch(x,y))
Or contained in two m-files:
function idx = substrmatch(word,cellarray)
idx = ~cellfun(#isempty,strfind(word,cellarray))
and
function newcell = findmatching(word,oldcell)
newcell = oldcell(substrmatch(word,oldcell))
So now you can just type
>> findmatching('words',cellArray)
ans =
'nicewords' 'morewords'
I don't know if you would consider it a simpler solution than yours, but regular expressions are a very good general-purpose utility I often use for searching strings. One way to extract the cells from cellArray that contains words with 'words' in them is as follows:
>> matches = regexp(cellArray,'^.*words.*$','match'); %# Extract the matches
>> matches = [matches{:}] %# Remove empty cells
matches =
'nicewords' 'morewords'

Resources