I am using cellstr in Matlab to convert characters to cell string array. For example:
A = 'a1a2a3a4...a100'; % I do not list all of the characters in A
B = cellstr(A);
But the result is
B = 'a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16a17a18a19a20a21a22a23a24a25a26a27a28a29a30a31a32a33a34a35a36a37a38a39a40a41a42a43a...'
It does not convert all the characters. I guess it is caused by the limit. Does anyone know how to increase this limit?
It does convert all of the characters. The ellipsis comes from Matlab truncating the output of a cell array display at the width of your command window.
You can display the full contents of the cell array using B{1}:
>> A = sprintf('a%g',1:100);
>> B = cellstr(A)
B =
'a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16a17a18a19a20a21a22a23a24a25a26a...'
>> B{1}
ans =
a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16a17a18a19a20a21a22a23a24a25a26a27a28a29a30a31a32a33a34a35a36a37a38a39a40a41a42a43a44a45a46a47a48a49a50a51a52a53a54a55a56a57a58a59a60a61a62a63a64a65a66a67a68a69a70a71a72a73a74a75a76a77a78a79a80a81a82a83a84a85a86a87a88a89a90a91a92a93a94a95a96a97a98a99a100
This is the default format for cell-strings such that as many elements of the array can be displayed in the command window at one time in limited space:
>> [B,B]
ans =
'a1a2a3a4a5a6a7a8a9a10a11a12a1...' 'a1a2a3a4a5a6a7a8a9a10a11a12a1...'
>> [B,B,B]
ans =
'a1a2a3a4a5a6a7a8...' 'a1a2a3a4a5a6a7a8...' 'a1a2a3a4a5a6a7a8...'
But, all of the string is contained within the cell array element itself. The only limit to the size is the amount of memory Matlab has to create the array.
Related
I am currently trying to read data from a text file written exactly like this:
Height = 10
Length = 10
NodeX = 11
NodeY = 11
K = 10
I've written a small code like this
fileID = fopen('input.dat','r');
[a, b] = fscanf(fileID, '%s %f')
And I get the following answer:
a =
72
101
105
103
104
116
b =
1
It seems quite obvious I am not mananging to specify the format specification.
I would like to know how to pick a string along with a float multiple times in the same file.
As the documentation for fscanf states:
If formatSpec contains a combination of numeric and character
specifiers, then fscanf converts each character to its numeric
equivalent. This conversion occurs even when the format explicitly
skips all numeric values (for example, formatSpec is '%*d %s').
MATLAB can be annoyingly bad at reading mixed data types. One possible alternative is to read each line and split up your data using a simple regular expression:
fileID = fopen('results.txt','r');
mydata = {};
ii = 1;
while ~feof(fileID) % While we're not at the end of the file
tline = fgetl(fileID); % Get next line
mydata(ii,:) = regexp(tline, '([a-zA-Z])* = (\d*)', 'tokens');
ii = ii + 1;
end
fclose(fileID);
This returns a 5 x 1 cell array where each cell contains 2 cells (slightly annoying, but you can pull them out) that match your data. In this case, mydata{1}{1} is Height and mydata{1}{2} is 10.
Edit:
And you can flatten your cell array with a reshape call:
mydata = reshape([mydata{:}], 2, [])';
Which turns mydata in this case into a 5x2 cell array.
The fscanf function is a low-level I/O function and is often not the best choice for such rather high-level file input. One alternative would be to use the textscan function, which allows quite advanced format specifications:
fileID = fopen('input.dat','r');
C = textscan(fileID,'%s = %d')
which creates a 1x2 cell array. The first cell C{1} contains another 5x1 cell, where each field contains the name of the field, e.g. 'Height'. The second cell C{2} contains a 5x1 vector containing all integer values from the file.
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);
I'm new to Matlab so bear with me. I have a text file in this form :
b0002 b0003 999
b0002 b0004 999
b0002 b0261 800
I need to read this file and convert it into a matrix. The first and second column in the text file are analogous to row and column of a matrix(the indices). I have another text file with a list of all values of 'indices'. So it should be possible to create an empty matrix beforehand.
b0002
b0003
b0004
b0005
b0006
b0007
b0008
Is there anyway to access matrix elements using custom string indices(I doubt it but just wondering)? If not, I'm guessing the only way to do this is to assign the first row and first column the index string values and then assign the third column values based on the first text file. Can anyone help me with that?
You can easily convert those strings to numbers and then use those as indices. For a given string, b0002:
s = 'b0002'
str2num(s(2:end); % output = 2
Furthermore, you can also do this with a char matrix:
t = ['b0002';'b0003';'b0004']
t =
b0002
b0003
b0004
str2num(t(:,2:end))
ans =
2
3
4
First, we use textscan to read the data in as two strings and a float (could use other numerical formats. We have to open the file for reading first.
fid = fopen('myfile.txt');
A = textscan(fid,'%s%s%f');
textscan returns a cell array, so we have to extract your three variables. x and y are converted to single char arrays using cell2mat (works only if all the strings inside are the same length), n is a list of numbers.
x = cell2mat(A{1});
y = cell2mat(A{2});
n = A{3};
We can now convert x and y to numbers by telling it to take every row : but only the second to final part of the row 2:end, e.g 002, 003 , not b002, b003.
x = str2num(x(:,2:end));
y = str2num(y(:,2:end));
Slight problem with indexing - if I have a matrix A and I do this:
A = magic(8);
A([1,5],[3,8])
Then it returns four elements - [1,3],[5,3],[1,8],[5,8] - not two. But what you want is the location in your matrix equivalent to x(1),y(1) to be set to n(1) and so on. To do this, we need to 1) work out the final size of matrix. 2) use sub2ind to calculate the right locations.
% find the size
% if you have a specified size you want the output to be use that instead
xsize = max(x);
ysize = max(y);
% initialise the output matrix - not always necessary but good practice
out = zeros(xsize,ysize);
% turn our x,y into linear indices
ind = sub2ind([xsize,ysize],x,y);
% put our numbers in our output matrix
out(ind) = n;
I have a 2D cell array with dynamic row sizes and column sizes. One example:
cell3 = [{'abe' 'basdasd' 'ceee'}; {'d' 'eass' 'feeeeeeeeee'}]
Gives: (with dimension 2 by 3)
'abe' 'basdasd' 'ceee'
'd' 'eass' 'feeeeeeeeee'
I want to be able to combine the columns and reproduce a aggregate string cell array where each string is separated by a single white space. Any idea how to do that?
So the output i am looking for is:
'abe basdasd ceee'
'd eass feeeeeeeeee'
The final dimension is 2 by 1.
Is this possible?
Apply strjoin either in a loop or via cellfun. The latter:
>> cellRows = mat2cell(cell3,ones(size(cell3,1),1),size(cell3,2));
>> out = cellfun(#strjoin,cellRows,'uni',0)
out =
'abe basdasd ceee'
'd eass feeeeeeeeee'
Solution without loops or cellfun:
[m n] = size(cell3);
cellCols = mat2cell(cell3,m,ones(1,n)); %// group by columns
cellColsSpace(1:2:2*size(cell3,2)-1) = cellCols; %// make room (columns)...
cellColsSpace(2:2:2*size(cell3,2)-1) = {{' '}}; %// ...to introduce spaces
%// Note that a cell within cell is needed, because of how strcat works.
result = strcat(cellColsSpace{:});
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)
.....