How to convert numeric results in symbols or strings? - matlab

this is my problem.
I made an algorithm that makes permutations of certain words. I substituted each word with a numeric value so I can make arithmetical operations with them (e.g. 1 = 'banana' 2 = 'child' 3 = 'car' 4 = 'tree' etc.).
Let's say that after running an algorithm, matlab gave me this matrix as result:
ans = [2,2,1; 4,3,3]
What I never can figure out is how to tell him - substitute digits with symbols and write:
ans = [child,child,banana; tree,car,car] - so I don't have to look up every number in my chart and replace it with a corresponding word!?

If you have an array with your words, and another array with the indices, you can produce an array that replaces every index with the corresponding word like so:
words = {'banana','child','car','tree'};
numbers = [2 2 1;4 3 3];
>> words(numbers)
ans =
'child' 'child' 'banana'
'tree' 'car' 'car'

You can also use the ordinal datatype if you have the statistics toolbox.
>> B = ordinal([2 2 0; 4 3 3], {'banana','child','car','tree'})
B =
child child banana
tree car car
Note that it handles zeros automatically. Then you can do things like:
>> B=='child'
ans =
1 1 0
0 0 0

Related

size of inner elements of cells

I'm reading some data with their attribute (say A in which first row is ids and second row is their attribute value) . I'd like to place such data in a cell where the first column are the unique ids and second row their attribute. whenever there's duplicate values for the attribute, I'll put on the vacancy available on front of its row. for example I'd like to construct C
A =
1 2 3 2
2 4 5 9
C{1}=
1 2 0
2 4 9
3 5 0
when I'm going to test the size of inner homes in cell, e.g.
size(C{1},2)
ans = 3
size(C{1},1)
ans = 3
size(C{1}(1,:),2)
ans = 3
All return 3 since it occupies empty homes with 0. So how should I understand where to put my new data (e.g. (1,5))? Should I traverse or find the place of 0 and insert there?
Thanks for any help.
Why not use a cell-Array for these kind of problem? How did you generate your C matrix?
Even though you have used cell-Arrays for C matrix, each element of C is a matrix in your case, so that the dimensions should be constant.
I have used a cell array inside a matrix. (i.e) each elements takes its own size based on the duplicate sizes. for eg, you could see that C{2,2} has two values while C{1,2} and C{3,2} has only one values. you could easily check the size of them without checking for zeros. Note that, even if any values were zero, this code will still work.
The first column of the matrix represents identifiers while the second column represents the values which takes its own size based on the number of duplicates.
Here is my Implementation using accumarray and unique to generate C as a cell-array.
Code:
C = [num2cell(unique(A(1,:).')), accumarray(A(1,:).',A(2,:).',[],#(x) {x.'})]
Your Sample Input:
A = [1 2 3 2;
2 4 5 9];
Output:
>> C
C =
[1] [ 2]
[2] [1x2 double]
[3] [ 5]
>> size(C{2,2},2)
ans =
2
>> size(C{1,2},2)
ans =
1
From the DOC
Note: If the subscripts in subs are not sorted with respect to their linear indices, then accumarray might not always preserve the order of the data in val when it passes them to fun. In the unusual case that fun requires that its input values be in the same order as they appear in val, sort the indices in subs with respect to the linear indices of the output.
Another Example:
Input:
A = [1 2 1 2 3 1;
2 4 5 9 4 8];
Output:
C =
[1] [1x3 double]
[2] [1x2 double]
[3] [ 4]
Hope this helps!!

Subset array to members of another array in Matlab

I am looking for a functionality i Matlab to subset and array like the IN function in SQL or %in% in R. I.e. I have the following data:
a = 1:3;
b = 2:4;
Then I want to write something like:
(a %in% b)
And it should produce:
ans =
0 1 1
However using %in% clearly doesn't work.
You are probably looking for the function ismember, which checks which members of one matrix are also member of a second matrix. It returns true/false for each entry in your matrix a if it can/cannot be found in your matrix b.
ismember(a, b)
ans =
0 1 1
As a side note: % is the character, which starts a comment.
You could also do it with bsxfun:
result = sum(bsxfun(#eq, a(:).', b(:)), 1);
This has the advantage that it tells you how many elements of b equal each element of a. For example,
>> a = [1 2 3];
>> b = [2 3 4 2];
>> result = sum(bsxfun(#eq, a(:).', b(:)),1)
result =
0 2 1

How to check if the beginning elements of array in matlab is the same

I would like to see if an array starts with the same elements as another array without having to write a bunch of for loops going through each element individually.
For example if I had the arrays below
Array1 = [1 2 3 4]
Array2 = [1 2 3 4 5 3 2 5 7]
Array3 = [1 2 3 5]
Then comparing Array1 with Array2 would return true.
and comparing Array3 with Array2 would return false.
Is there any quick and easy way of doing this. I would not know the lengths of the arrays I would be comparing. The number of elements I want to compare equals the length of the shortest vector.
Thanks!
You can check if all elements in two vectors are the same using isequal. To check only the first n elements, you can do Array(1:n), thus the entire function will be like this:
Array1 = [1 2 3 4]
Array2 = [1 2 3 4 5 3 2 5 7]
Array3 = [1 2 3 5]
n = 4; % Compare the first n elements
isequal(Array1(1:n), Array2(1:n))
ans = 1
isequal(Array2(1:n), Array3(1:n))
ans = 0
If you use Array1(1:n) == Array2(1:n) you will get a piece-wise comparison resulting in 1 1 1 1. Of course, this means you could also do:
all(Array1(1:n) == Array2(1:n))
ans = 1
all(Array2(1:n) == Array3(1:n))
ans = 0
If you want n to be the number of elements in the smallest vector (per your comment), as Chris and Ben interpret the question, you can solve it this way:
isequal(Array1(min([numel(Array1) numel(Array2)])), Array2(min([numel(Array1) numel(Array2)])))
or a bit cleaner:
n = min([numel(Array1) numel(Array2)])
isequal(Array1(1:n), Array2(1:n))
Here's a function that will compare the initial segments of any two vectors, up to the length of the shortest vector. It returns true if they are identical, and false if they are not identical.
Note that
It only works correctly with vectors, not with matrices (although you could extend it to deal with matrices)
If any entries are NaN then it will always return false, since NaN == NaN is false.
Here it is -
function result = equal_initial_segment(x, y)
N = min(length(x), length(y));
result = isequal(x(1:N), y(1:N));
end
It seems like you are just comparing the all of the elements of the shorter list to the first elements of the longer list, in which case you can just do this:
function same = compareLists(list1, list2)
if length(list1) > length(list2)
same = isequal(list2, list1(1:length(list2));
else if
same = isequal(list1, list2(1:length(list1));
end
end
You can use strmatch for that:
~(isempty(strmatch(Array1, Array2)) && isempty(strmatch(Array2, Array1)))

MATLAB Incorrect number of right hand side elements

Matlab's syntax is infuriating, specifically with structs. In the Bioinformatics toolkit, there is a method called jcampread(File) which is described here.
In the description, the method jcampread() takes a Filepath and outputs into a struct called jcampStruct. From my understanding, in Matlab, you don't declare return variable types like you do in C: you just give the return variable a name and it somehow knows that the return of jcampread() method will be a jcampStruct. How it does, I have no idea, but it does.
I put in the code exactly how their example shows in step 4 of the Example section, and I get the following error message back from Matlab:
Incorrect number of right hand side elements in
dot name assignment. Missing [] around left hand
side is a likely cause.
Error in jcampread>ntupleRead (line 510)
dataBlock.ZName = name{Zidx};
Error in jcampread (line 192)
dataBlocks = ntupleRead(fid);
This site says the problem occurs "when f has more than one matrix element." Code is below:
»f.a = [1 0]
f =
a: [1 0]
»f.b = [1 2]
f =
a: [1 0]
b: [1 2]
»f = setfield(f,'a',[2 2])
f =
a: [2 2]
b: [1 2]
»f(2).a=1
f =
1x2 struct array with fields:
a
b
»f = setfield(f,'a',[2 2])
??? Error using ==> setfield
Incorrect number of right hand side elements in dot name assignment.
Missing [] around left hand side is a likely cause.
I assume this means the matrix f looks like this:
f = [ [a1; b1]; [a2; b2]; ]
f = [ [[2 2]; [1 2]]; [[1]; []]; ]
When they tried to update f.a which was set to
f.a = [[2 2]; [1]]
...to a single element [2 2], it doesn't like that because f.a is currently a matrix with 2 vector elements. Basically if you are going to reassign f.a (all elements of the attribute a of matrix f), you have to reassign f.a to have the same number of elements as it currently has.
I think that is why this error is occuring in the setfield example.
My question: how does this apply to jcampread()? jcampStruct is literally a structure with the same attributes, and those attributes are assigned only once. I do not understand:
a. How matlab knows the return value of jcampread() is a jcampStruct, and
b. Why (given that it knows (a)), the 'Incorrect number of right hand..' error message is firing here.
Can anyone clear this up for me?
You are creating a non scalar structure and there is no way to assign at once, i.e. without a loop, a different value to the same field of each sub-structure.What does it mean?
Scalar structure
s.a = 1;
size(s)
ans =
1 1
Now, adding fields doesn't change the size of the structure:
s.b = 2;
size(s)
ans =
1 1
Non-scalar structure
However, assigning a value to the same field, but into a position > 1 of the structure, will grow it a non-scalar one:
s(2).a = 3
size(s)
ans =
1 2
Also, notice how the sub-structure in position 2 replicates/pre-allocates the fields of the initial structure even though you assigned to a alone:
s(2)
ans =
a: 3
b: []
Pointers
Additionally, the field s(2).b is just an empty pointer:
whos s
Name Size Bytes Class
s 1x2 496 struct
and by adding a scalar double (8 bytes), we get
s(2).b = 4;
whos s
Name Size Bytes Class
s 1x2 608 struct
Pro of non-scalar structure
What you can do with a non-scalar structure, is retrieve one field across all sub-structure (considering you don't run into concatenation issues):
for ii = 1:100
s(ii).a = rand(1,2);
end
cat(1,s.a)
the last command will concatenate all values of a single field from all sub-structure into a 100 by 2 array.
Cons
To assign different values across the sub-structures, even if the same field, you need to loop (as above in the for loop).
At most you could deal() the same values into one field across all sub-structures:
clear s
[s(1:100)] = deal([1, 2]);

How to calculate possible word subsequences matching a pattern?

Suppose I have a sequence:
Seq = 'hello my name'
and a string:
Str = 'hello hello my friend, my awesome name is John, oh my god!'
And then I look for matches for my sequence within the string, so I get the "word" index of each match for each word of the sequence in a cell array, so the first element is a cell containing the matches for 'hello', the second element contains the matches for 'my' and the third for 'name'.
Match = {[1 2]; %'hello' matches
[3 5 11]; %'my' matches
[7]} %'name' matches
I need code to somehow get an answer saying that possible sub-sequence matches are:
Answer = [1 3 7; %[hello my name]
1 5 7; %[hello my name]
2 3 7; %[hello my name]
2 5 7;] %[hello my name]
In such a way that "Answer" contains all possible ordered sequences (that's why my(word 11) never appears in "Answer", there would have to be a "name" match after position 11.
NOTE: The length and number of matches of "Seq" may vary.
Since the length of Matches may vary, you need to use comma-separated lists, together with ndgrid to generate all combinations (the approach is similar to that used in this other answer). Then filter out combinations where the indices are not increasing, using diff and logical indexing:
cc = cell(1,numel(Match)); %// pre-shape to be used for ndgrid output
[cc{end:-1:1}] = ndgrid(Match{end:-1:1}); %// output is a comma-separated list
cc = cellfun(#(v) v(:), cc, 'uni', 0) %// linearize each cell
combs = [cc{:}]; %// concatenate into a matrix
ind = all(diff(combs.')>0); %'// index of wanted combinations
combs = combs(ind,:); %// remove unwanted combinations
The desired result is in the variable combs. In your example,
combs =
1 3 7
1 5 7
2 3 7
2 5 7