How to convert the string 'pi' to double? (MATLAB 2015a) - matlab

When I try to convert the string 'pi' to a double it gets converted to NaN.
>> str2double('pi')
ans =
NaN
I'm reading a file that contains comma separated values, which might include a multiple of pi. For example (assume pi_in_string was read from a file):
>> pi_in_string = '0,1,-pi/6'
pi_in_string =
0,1,-pi/6
>> split_string = strsplit(pi_in_string, ',')
split_string =
'0' '1' '-pi/6'
>> str2double(split_string)
ans =
0 1 NaN

I figured out that I need to use str2num instead of str2double, but str2num doesn't work on a cell array. So instead, I looped through the elements in the cell array, converting each to type char first, then using str2num.
pi_in_string = '0,1,-pi/6';
str_array = strsplit(pi_in_string, ','); %str_array now cell array
num_elements = length(str_array); %get # elements to loop
num_vector = zeros(1,num_elements); %initialize vector
%loop through elements in str_array
for i = 1:num_elements %converting each element first to type char
num_vector(i) = str2num(char(str_array(i)));
end

It is easy to avoid the for loop and explicitly initializing the num_vector array using the cellfun command:
pi_in_string = '0,1,-pi/6';
str_array = strsplit(pi_in_string, ',');
num_vector = cellfun(#(x)eval(x), str_array, 'UniformOutput', true)
num_vector =
0 1.0000 -0.5236

Related

How to convert a struct to a matrix

I have a 10 x 10 struct with four fields a,b,c,d.
How do I convert this struct to a 10 x 10 matrix with entries only from the field a?
You can rely on the fact that str.a returns a comma-separated list. We can therefore concatenate the values together and reshape the resulting array to be the same size as the input struct.
% If a contains scalars
out = reshape([str.a], size(str));
% If a contains matrices
out = reshape({str.a}, size(str));
One liner solution
res = cellfun(#(strctObj) strctObj.a,str,'UniformOutput',false);
Further explanation
Define a one-line function which extract the a value.
getAFunc = #(strctObj) strctObj.a;
use MATLAB's cellfun function to apply it on your cell and extract the matrix:
res = cellfun(#(strctObj) getAFunc ,strctCellObj,'UniformOutput',false);
Example
%initializes input
N=10;
str = cell(N,N);
for t=1:N*N
str{t}.a = rand;
str{t}.b = rand;
str{t}.c = rand;
str{t}.d = rand;
end
%extracts output matrix
res = cellfun(#(strctObj) strctObj.a,str,'UniformOutput',false);

how to convert char to number in matlab?

Please help me with the following problem:
In matlab, I have an Nx3 char variable, where N can vary depending on the input.
Let's say N = 5 and I have the following variable A (5x3 char):
A = [' 1Y';
' 5Y';
'10Y';
'15Y';
'20Y']
Is there a way to define a new variable B having as values the numbers in variable A, i.e. B=[1; 5; 10; 15; 20]?
Thank you for your help!
Since your input is a character array, first convert each row into a cell to allow use with the string functions in MATLAB:
out = mat2cell(val, ones(size(val,1),1));
mat2cell converts a matrix into a series of cells. In our case, you would like to have 5 cells, or as many cells as there are rows in your matrix val and each cell will be as long as the total number of column in val.
Once you do this, you can replace the Y strings with nothing, then convert to numbers:
out = strrep(out, 'Y', '');
out2 = cellfun(#str2num, out);
The first line uses strrep to replace any instances of Y with nothing, and then we apply str2num on each of the cells to convert the trimmed string into an actual number. This is through the use of cellfun so that we can iterate through each cell apply str2num to each cell.
We get:
out2 =
1
5
10
15
20
To be fully reproducible:
val = ['1Y '; '5Y '; '10Y'; '15Y'; '20Y'];
out = mat2cell(val, ones(size(val,1),1), size(val,2));
out = strrep(out, 'Y', '');
out2 = cellfun(#str2num, out);
Suppose you have the following:
A = [' 1Y';
' 5Y';
'10Y';
'15Y';
'20Y';]
Then this should do the trick:
B=A'
C=strsplit(B(:)','Y')
V=cellfun(#str2num,C(1:end-1))
This is how you can convert a cellstr to its numeric value:
a = {'1'};
ans1 = int64(str2num(a{1}));

Exporting blank values into a .txt file - MATLAB

I'm currently trying to export multiple matrices of unequal lengths into a delimited .txt file thus I have been padding the shorter matrices with 0's such that dlmwrite can use horzcat without error:
dlmwrite(filename{1},[a,b],'delimiter','\t')
However ideally I do not want the zeroes to appear in the .txt file itself - but rather the entries are left blank.
Currently the .txt file looks like this:
55875 3.1043e+05
56807 3.3361e+05
57760 3.8235e+05
58823 4.2869e+05
59913 4.3349e+05
60887 0
61825 0
62785 0
63942 0
65159 0
66304 0
67509 0
68683 0
69736 0
70782 0
But I want it to look like this:
55875 3.1043e+05
56807 3.3361e+05
57760 3.8235e+05
58823 4.2869e+05
59913 4.3349e+05
60887
61825
62785
63942
65159
66304
67509
68683
69736
70782
Is there anyway I can do this? Is there an alternative to dlmwrite which will mean I do not need to have matrices of equal lengths?
If a is always longer than b you could split vector a into two vectors of same length as vector b and the rest:
a = [1 2 3 4 5 6 7 8]';
b = [9 8 7 ]';
len = numel(b);
dlmwrite( 'foobar.txt', [a(1:len), b ], 'delimiter', '\t' );
dlmwrite( 'foobar.txt', a(len+1:end), 'delimiter', '\t', '-append');
You can read in the numeric data and convert to string and then add proper whitespaces to have the final output as string based cell array, which you can easily write into the output text file.
Stage 1: Get the cell of strings corresponding to the numeric data from column vector inputs a, b, c and so on -
%// Concatenate all arrays into a cell array with numeric data
A = [{a} {b} {c}] %// Edit this to add more columns
%// Create a "regular" 2D shaped cell array to store the cells from A
lens = cellfun('length',A)
max_lens = max(lens)
A_reg = cell(max_lens,numel(lens))
A_reg(:) = {''}
A_reg(bsxfun(#le,[1:max_lens]',lens)) = cellstr(num2str(vertcat(A{:}))) %//'
%// Create a char array that has string data from input arrays as strings
wsp = repmat({' '},max_lens,1) %// Create whitespace cell array
out_char = [];
for iter = 1:numel(A)
out_char = [out_char char(A_reg(:,iter)) char(wsp)]
end
out_cell = cellstr(out_char)
Stage 2: Now, that you have out_cell as the cell array that has the strings to be written to the text file, you have two options next for the writing operation itself.
Option 1 -
dlmwrite('results.txt',out_cell(:),'delimiter','')
Option 2 -
outfile = 'results.txt';
fid = fopen(outfile,'w');
for row = 1:numel(out_cell)
fprintf(fid,'%s\n',out_cell{row});
end
fclose(fid);

Read string from txt file and use string for loop

Trying to read a txt file, then to loop through all string of the txt file. Unfortunately not getting it to work.
fid = fopen(fullfile(source_dir, '1.txt'),'r')
read_current_item_cells = textscan(fid,'%s')
read_current_item = cell2mat(read_current_item_cells);
for i=1:length(read_current_item)
current_stock = read_current_item(i,1);
current_url = sprintf('http:/www.', current_item)
.....
I basically try to convert the cell arrays to a matrix as textscan outputs cell arrays. However now I get the message
Error using cell2mat (line 53) Cannot support cell arrays containing cell arrays or objects.
Any help is very much appreciated
That is the normal behaviour of textscan. It returns a cell array where each element of it is another cell OR array (depending on the specifier) containing the values corresponding to each format specifier in the format string you have passed to the function. For example, if 1.txt contains
appl 12
msft 23
running your code returns
>> read_current_item_cells
read_current_item_cells =
{4x1 cell}
>> read_current_item_cells{1}
ans =
'appl'
'12'
'msft'
'23'
which itself is another cell array:
>> iscell(read_current_item_cells{1})
ans =
1
and its elements can be accessed using
>> read_current_item_cells{1}{1}
ans =
appl
Now if you change the format from '%s' to '%s %d' you get
>> read_current_item_cells
read_current_item_cells =
{2x1 cell} [2x1 int32]
>> read_current_item_cells{1}
ans =
'appl'
'msft'
>> read_current_item_cells{2}
ans =
12
23
But the interesting part is that
>> iscell(read_current_item_cells{1})
ans =
1
>> iscell(read_current_item_cells{2})
ans =
0
That means the cell element corresponding to %s is turned into a cell array, while the one corresponding to %d is left as an array. Now since I do not know the exact format of the rows in your file, I guess you have one cell array with one element which in turn is another cell array containing all the elements in the table.
What can happen is that the data gets wrapped into a cell array of cell arrays, and to access the stored strings you need to index past the first array with
read_current_item_cells = read_current_item_cells{1};
Converting from cell2mat will not work if your strings are not equal in length, in which case you can use strvcat:
read_current_item = strvcat(read_current_item_cells{:});
Then you should be able to loop through the char array:
for ii=1:size(read_current_item,1)
current_stock = read_current_item(ii,:);
current_url = sprintf('http:/www.', current_stock)
.....

find NaN values is cell array

lets assume I have the following array:
a = {1; 'abc'; NaN}
Now I want to find out in which indices this contains NaN, so that I can replace these with '' (empty string).
If I use cellfun with isnan I get a useless output
cellfun(#isnan, a, 'UniformOutput', false)
ans =
[ 0]
[1x3 logical]
[ 1]
So how would I do this correct?
Indeed, as you found yourself, this can be done by
a(cellfun(#(x) any(isnan(x)),a)) = {''}
Breakdown:
Fx = #(x) any(isnan(x))
will return a logical scalar, irrespective of whether x is a scalar or vector.
Using this function inside cellfun will then erradicate the need for 'UniformOutput', false:
>> inds = cellfun(Fx,a)
inds =
0
0
1
These can be used as indices to the original array:
>> a(inds)
ans =
[NaN]
which in turn allows assignment to these indices:
>> a(inds) = {''}
a =
[1]
'abc'
''
Note that the assignment must be done to a cell array itself. If you don't understand this, read up on the differences between a(inds) and a{inds}.
I found the answer on http://www.mathworks.com/matlabcentral/answers/42273
a(cellfun(#(x) any(isnan(x)),a)) = {''}
However, I do not understant it...
a(ind) = [] will remove the entries from the array
a(ind)= {''} will replace the NaN with an empty string.
If you want to delete the entry use = [] instead of = {''}.
If you wanted to replace the NaNs with a different value just set it equal to that value using curly braces:
a(ind) = {value}