Matlab: convert cell to readable format - matlab

Thanks in advance for the help.
I have an array of values that looks like this
[[1x5 double]; [1x2 double]; ....]
I would like to convert this to this
['12345'; '12'; ....]
cell2mat sort of does what I want, but I end up getting this
[['1' '2' '3' '4' '5']; ['1' '2'];...]
I have been all over the matlab documentation and haven't found a way to do this. Really all I want is to convert [1x5 double] to a string (I can't convert to a num because I don't want to drop insignificant zeros). Is there an simple easy way to do this besides doing this by hand with for loops?

If input_array is your input array, try this cellfun + num2str based approach -
cellfun(#(x) num2str(x,'%1d'), input_array,'uni',0)
Example -
%// Input array
input_array = {randi(9,1,5)-1;randi(9,1,2)-1}
%// Display the cell array values for verification of results later on
celldisp(input_array)
%// Output
out = cellfun(#(x) num2str(x,'%1d'), input_array,'uni',0)
Output (on run) -
input_array =
[1x5 double]
[1x2 double]
input_array{1} =
3 6 0 5 3
input_array{2} =
6 2
out =
'36053'
'62'

Related

splitting a character array into a cell array and matrix

I have a text file.
In the file is approx 20,000 rows of data. Each row has one column & contains 256 characters (which are all numbers).
I need to split each row into a cell array or matrix. So each 8 characters are "one piece" of information. I want to split the first 3 characters into a cell array and the next 5 characters into a double, then same again for the next 8 characters.
example
1653256719812345
myCellArray (1 x 2) myDoubleArray (1 x 2)
[165, 198] [32567, 12345]
What is the best way to do this?
Use textscan.
fid = fopen(MyFileName.txt);
data = textscan(fid, '%3d%5d', 'Delimiter', '');
fclose(fid);
testing:
% Test with string of 256 random digits that all happen to be 1:8 repeated 32 times
x = '1234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678';
>> y = textscan(x, '%3d%5d', 'Delimiter', '')
y =
[32x1 int32] [32x1 int32]
>> y{1}
ans =
123
123
123
123
...
I don't know the exact format of your files, so you may have to do this line-by-line within a loop (in which case you would get each line using fgetl and then replace fid in the textscan statement with the output from fgetl).
In general, whenever you find yourself having to read in data that was produced by FORTRAN code (fixed field width text files), textscan's 'Delimiter, '' and 'Whitespace', '' parameters are your friend.
Use regexp. If the file data.txt contains
1653256719812345
1563256719812345
1233256719812345
1463256719812345
Then the following MATLAB statements will read the numbers.
>> txt = fileread('data.txt') % Read entire file in txt
>> out = regexp(txt,'(\d{3})(\d{5})(\d{3})(\d{5})','tokens') % Match regex capturing groups
out =
{1x4 cell} {1x4 cell} {1x4 cell} {1x4 cell}
Each cell in out is a row from the file containing the parsed numbers as strings.You can use str2double to convert the numbers to a numeric data type in MATLAB
>> nums = cellfun(#str2double,out,'uni',0)
nums =
[1x4 double] [1x4 double] [1x4 double] [1x4 double]
Iterate over your rows one by one and run something like the following code.
k=int2str(1653256719812345);
> myCellArray{1}=k(1:3)
myCellArray =
'165'
>> mydoublearray(1)=str2num(k(4:9))
mydoublearray =
325671
If there's some formulaic pattern you should incorporate that instead of manually hard coding it.

How do I remove the elements of one vector from another?

I have a double value, A, which is
[1,4,7,6]
I also have B, which is an array that contains many more values. I have a new variable, C, which is essentially a double value of all these numbers (all of them in one cell, vs. five).
[1,4,7,6]
[2,6,9,12]
[3,1,17,13]
[5,7,13,19]
[1,5,9,15]
How do I remove the elements (not the actual values) from C? I want to end up with this.
[2,6,9,12,3,1,17,13,5,7,13,19,1,5,9,15]
How do I get this? I've used these commands:
C(A) = [];
and
C = C(setdiff(1:length(C),A));
The problem is that when I run that command, I get this instead of what I want.
[4,7,2,12,3,1,17,13,5,7,13,19,1,5,9,15]
Clearly that isn't the same as what I have. It's throwing off the rest of my results and I need to fix this specific issue.
Thanks in advance :)
EDIT:
So I figured out that it's spewing the CORRECT numbers out, just in the wrong order. I have to sort it in order for it to work correctly. This is a problem because it causes the next command to be non-functional because the ismember command has issues with the removal (I don't know why, I'm still working on it).
Double array case
If B is a double array, you can use setdiff with 'rows' and 'stable' options, like so -
C = reshape(setdiff(B,A,'rows','stable').',1,[])
With ismember, you can perform the same operation, like so -
C = reshape(B(~ismember(B,A,'rows'),:).',1,[])
You can also use a bsxfun approach as suggested by #Amro -
C = reshape(B(~all(bsxfun(#eq, B, A),2),:).',1,[])
Cell array case
If B is a cell array with number of elements in each cell equal to the number of elements in A, then you can firstly convert it to a double array - B = vertcat(B{:}) and then use either of the above mentioned tools.
Or you can use a cellfun based approach that avoids conversion to a double array, like so -
excl_rows = B(~cellfun(#(x1,x2) isequal(x1,x2), B, repmat({A},size(B,1),1)),:)
C = horzcat(excl_rows{:})
Or another cellfun based approach that avoids repmat -
exclB = B(~cellfun(#(x1) isequal(x1,A), B),:)
C = horzcat(exclB{:})
Example with explanation -
%// Inputs
A = [1,4,7,6]
B = {[1,4,7,6]
[2,6,9,12]
[3,1,17,13]
[5,7,13,19]
[1,5,9,15]}
%// Compare each cell of B with A for equality.
%// The output must be a binary array where one would be for cells that have
%// elements same as A and zero otherwise.
ind = cellfun(#(x1) isequal(x1,A), B)
%// Thus, ~ind would be a binary array where one would reperesent unequal
%// cells that are to be selected in B for the final output.
exclB = B(~ind)
%// exclB is still a cell array with the cells that are different from A.
%// So, concatenate the elements from exclB into a vector as requested.
C = horzcat(exclB{:})
Output -
A =
1 4 7 6
B =
[1x4 double]
[1x4 double]
[1x4 double]
[1x4 double]
[1x4 double]
ind =
1
0
0
0
0
exclB =
[1x4 double]
[1x4 double]
[1x4 double]
[1x4 double]
C =
2 6 9 12 3 1 17 13 5 7 13 19 1 5 9 15

MATLAB: Structure containing an column vector won't display the vector

I have defined a structures array as such:
oRandVecs = struct('vV',{[],[]},...
'ind_min',{[],[]},...
'mean',{[],[]},...
'vV_descending',{[],[]},...
'largest_diff',{[],[]});
oRandVecs(1).vV and oRandVecs(2).vv both get column vectors assigned to them. However, the problem is that the output is as follows:
>> oRandVecs(1)
ans =
vV: [4x1 double]
ind_min: 2
mean: 6.5500
vV_descending: [4x1 double]
largest_diff: 2.8000
Instead of actually showing the vector, it only describes its type.
What am I to do?
The reason why is because it's simply too big to display on the screen with that structure :) If you want to actually display it, use dot notation to display your data.
In other words, do this:
disp(oRandVecs(1).vV);
You can also do that with the other variable:
disp(oRandVecs(1).vV_descending);
The answer by rayryeng is probably the way to go.
An alternative is to convert from structure to cell and then use celldisp:
celldisp(struct2cell(oRandVecs(1)))
Example:
>> oRandVecs = struct('vV',{[],[]},...
'ind_min',{[],[]},...
'mean',{[],[]},...
'vV_descending',{[],[]},...
'largest_diff',{[],[]}); %// define empty struct
>> oRandVecs(1).vV = (1:4).'; %'// fill some fields: column vector, ...
>> oRandVecs(1).mean = 5:7; %// ... row vector, ...
>> oRandVecs(1).vV_descending = randn(2,3); %// ... matrix
>> celldisp(struct2cell(oRandVecs(1)))
ans{1} =
1
2
3
4
ans{2} =
[]
ans{3} =
5 6 7
ans{4} =
0.016805198757746 0.236095190511728 0.735153386198679
2.162769508502985 -0.158789830267017 0.661856091557715
ans{5} =
[]

How can I group variables from a mat file by name and collect them in a structure?

I'm reading in a mat file which has variables with a counter e.g. a1, a2, a3, b, c1 and c2.
I want to put the data into a structure with field names "a", "b" and "c" where
a=[a1;a2;a3], b=b and c = [c1; c2].
The algorithm needs to be able to do this, without knowing what the maximum value of the counter of each variable is. How can I do this?
First, you would load your mat file data using the load function, placing it in a structure. Let's say that gave you the following sample data:
>> s = struct('a1',1:5,'b',[],'a2',1:5,'a3',1:5,'c1',1:3,'c2',3:5)
s =
a1: [1 2 3 4 5]
b: []
a2: [1 2 3 4 5]
a3: [1 2 3 4 5]
c1: [1 2 3]
c2: [3 4 5]
Then, we'll order the fields alphabetically using orderfields, find the field names using fieldnames, use regexprep to strip all trailing numbers off of the field names, then get the unique substrings using unique:
>> s = orderfields(s);
>> [strs, inds] = unique(regexprep(fieldnames(s), '\d*$', ''), 'last')
strs =
'a'
'b'
'c'
inds =
3
4
6
Using the indices returned by unique, we can calculate how many times each substring appears by doing diff([0; inds]). Then, we group the structure data into a cell array using these counts and struct2cell and mat2cell:
>> data = mat2cell(struct2cell(s), diff([0; inds]))
data =
{3x1 cell}
{1x1 cell}
{2x1 cell}
Notice that we have a cell array of cell arrays. If you know for sure that each set of entries for each substring will concatenate properly (as in our example), you can concatenate them using cellfun and cell2mat as follows:
>> data = cellfun(#cell2mat, data, 'UniformOutput', false)
data =
[3x5 double]
[]
[2x3 double]
Now we have a cell array of matrices, and a new structure can be made using cell2struct:
>> snew = cell2struct(data, strs)
snew =
a: [3x5 double]
b: []
c: [2x3 double]

double array in cell, how to indexing?

I have an cell including array as below format
a{x,y,z}(i,j)
a is 3 dimensional cell
and
each cell have i*j array
a <79x95x68 cell>
val(:,:,1) =
Columns 1 through 2
[6x6 double] [6x6 double]
[6x6 double] [6x6 double]
[6x6 double] [6x6 double]
i want to rearrange that as below format
a{i,j}(x,y,z)
how to? any good idea? i have to do iteration?
matlab say, a{:,:}(x,y,z) is bad cell referencing.........
here's a suboptimal way to go, it isn't memory efficient, but it is pretty straightforward:
say that x=79,y=95,z=68 are the dimensions of your original cell array, and that each of them gives the same dimensionality ixj matrix (6 by 6). So first you can make a matrix out of the cell array:
b=horzcat(a{:});
then we can reshape it to a 5-d array (this is just for pedagogical purposes) so you already have it ordered as (i,j,x,y,z)...
c=reshape(b,6,6,x,y,z);
then you can either work with c(i,j,x,y,z), or assign c to a cellarray:
d=cell(6,6);
for i=1:6
for j=1:6
d{i,j}=squeeze(c(i,j,:,:,:));
end
end