Adding a datapoint to datastruct in matlab - matlab

I am trying to add a datapoint to an existing data struct. I have created the following data struct.
ourdata.animal= {'wolf', 'dog', 'cat'}
ourdata.height = [110 51 32]
ourdata.weight = [55 22 10]
say I want to add another one to the data struct with name 'fish' height 3 and weight 1, how do I go about this?

You can simply attach it to the end of the structure:
ourdata.animal{end+1} = 'fish'
ourdata.height(end+1) = 3
ourdata.weight(end+1) = 1

If you want to work with multiple structures, you can write a little function to combine the values of fields in multiple structs. Here's one, using fieldnames() to discover what fields exist:
function out = slapItOn(aStruct, anotherStruct)
% Slap more data on to the end of fields of a struct
out = aStruct;
for fld = string(fieldnames(aStruct))'
out.(fld) = [aStruct.(fld) anotherStruct.(fld)];
end
end
Works like this:
>> ourdata
ourdata =
struct with fields:
animal: {'wolf' 'dog' 'cat'}
height: [110 51 32]
weight: [55 22 10]
>> newdata = slapItOn(ourdata, struct('animal',{{'bobcat'}}, 'height',420, 'weight',69))
newdata =
struct with fields:
animal: {'wolf' 'dog' 'cat' 'bobcat'}
height: [110 51 32 420]
weight: [55 22 10 69]
>>
BTW, I'd suggest that you use string arrays instead of cellstrs for storing your string data. They're better in pretty much every way (except performance). Get them with double quotes:
>> strs = ["wolf" "dog" "cat"]
strs =
1×3 string array
"wolf" "dog" "cat"
>>
Also, consider using a table array instead of a struct array for tabular-looking data like this. Tables are nice!
>> animal = ["wolf" "dog" "cat"]';
>> height = [110 51 32]';
>> weight = [55 22 10]';
>> t = table(animal, height, weight)
t =
3×3 table
animal height weight
______ ______ ______
"wolf" 110 55
"dog" 51 22
"cat" 32 10
>>

Related

What the best way to build a dictionary (word count) for NLP in matlab?

I have a frequency count dictionary, I want to be able to read the frequency count to a given word in my dictonary.
for example
my input word is 'about' ,so the output will be the count of 'about' in my dictionary, which 139 to be able to calculate the probability.
139 about
133 according
163 accusing
244 actually
567 afternoon
175 again
156 ah
167 a-ha
165 ahh
I tried do this with fopen method, but not getting the wanted result.
1 fid = fopen('dictionary.txt');
2 words = textscan(fid, '%s');
3 fclose(fid);
4 words = words{1};
I tried this as well, but getting different result,
countfunction = #(word) nnz(strcmp(word, words));
count = cellfun(countfunction, words);
tally = [words num2cell(count)];
sortrows(tally, 2);
The problem is that you're running countfunction for each instance of each word in the dictionary, rather than each unique word in the dictionary.
Here's how to incrementally improve your code:
words = {'hi' 'hi' 'the' 'hi' 'the' 'a'};
unique_words = unique(words(:));
countfunction = #(word) nnz(strcmp(word, words));
count = cellfun(countfunction, unique_words);
tally = [unique_words, num2cell(count)];
disp(sortrows(tally, 2));
'a' [1]
'the' [2]
'hi' [3]
However, I'd recommend using grpstats instead:
words = {'hi' 'hi' 'the' 'hi' 'the' 'a'};
[unique_words, count] = grpstats(ones(size(words)), words(:), {'gname', 'numel'});
tally = [unique_words, num2cell(count)];
disp(sortrows(tally, 2));
'a' [1]
'the' [2]
'hi' [3]

Matlab: structures with variable name as index

I am not sure this is possible in Matlab but wanted to make sure.
I have structures as:
x = struct();
x.val1 = 5;
x.val2 = 7;
y = struct();
y.val1 = 15;
y.val2 = 17;
I want to create a structure DataStore as:
DataStore = struct;
DataStore(x).val1 = 5
DataStore(x).val2 = 7
DataStore(y).val1 = 15
DataStore(y).val2 = 17
OR
DataStore = struct;
DataStore('x').val1 = 5
DataStore('x').val2 = 7
DataStore('y').val1 = 15
DataStore('y').val2 = 17
So, I am using the name of the original structure variables as index for DataStore.
Is the above feasible ?
Edit:
I aim to use DataStore as following:
disp( DataStore('x').val1 )
disp( DataStore('y').val2 )
Use a struct, maybe with dynamic field names.
Either:
DataStore.x.val1=6
DataStore.x.val2=9
Alternative with dynamic filed names (result is the same):
f='x'
DataStore.(f).val1=6
DataStore.(f).val2=9
In case val1 and val2 are not just placeholders, concider replacing them with an array:
DataStore.(f).val(1)=6
DataStore.(f).val(2)=9

MATLAB - Sort struct by substruct field

I'm a new Matlab user and a I have some doubts about structs.
My case is:
I have a struct P1 that have 3 "substructs"( A1, A2, A3) with two fields(Name and Age) and I want to sort my "substructs" by age. So, I have it:
P1.A1.age = 33
P1.A2.age = 23
P1.A3.age = 31
and I want this results:
P1.A2.age = 23
P1.A3.age = 31
P1.A1.age = 33
Any idea?
I try to use the function orderfields, but I didn't have the results that I wish.
Thanks !!!
First get the required permutation for sorting using sort and structfun. Then apply that permutation using orderfields:
[~, I] = sort(structfun(#(x) x.age, P1));
P1 = orderfields(P1, I);
Will this work for you?
>> [val idx]=sort(arrayfun(#(x) P1.(sprintf('A%d',x)).age,1:3))
val =
23 31 33
idx =
2 3 1

read input file Matlab

I have a problem while reading an input file in Matlab. It appears that all the rows have one parameter input except for the last one which is a vector:
INPUT FILE
--------------
Field1: number
Field2: text (one word)
Field3: number
Field4: number
Field5: number
Field6: number
Field7: vector
The code I have implemented looks like:
fid = fopen('input.inp','r');
A = textscan(fid,'%s %f','Delimiter','\t','headerLines',2);
data = cat(2,A{:});
I would like some help to deal with the fact that I have some text/number cases and also to deal with the vector form the last row. Thanks
Is this what you are looking for...?
I think you have to use %s %s as a format to text scan and not a float because a vector cannot be converted to a float for example.
I changed this A = textscan(fid,'%s %s','Delimiter','\t'); to include %s %s.
Also, I think you want to concatenate along the first dimension rather than the second.
I think you actually want to create a key/value pair of the input file rather than just reading each row into a cell but you don't state that.
INPUT FILE
--------------
Field1: 1
Field2: two
Field3: 3
Field4: 4
Field5: 5
Field6: 6
Field7: [7 8 9]
fid = fopen('D:\tmp\t.txt','r');
A = textscan(fid,'%s %s','Delimiter','\t','headerLines',2);
cat(1,A{:})
ans =
{
[1,1] = Field1: 1
[2,1] = Field3: 3
[3,1] = Field5: 5
[4,1] = Field7: [7 8 9]
[5,1] = Field2: two
[6,1] = Field4: 4
[7,1] = Field6: 6
}
If you want to create a key/value pair, then you can split them into key and value with a loop that you can use with the Container class if needed. You have to filter your strings a bit (e.g remove colons etc) but you get the gist.
keySet = {};
valueSet = {};
for (n=1:size(A2,1))
s = A2{n};
ind = strfind(s,' ');
keySet{n} = s(1:ind(1));
valueSet{n} =s(ind(1):end);
end
The output is
keySet =
{
[1,1] = Field1:
[1,2] = Field3:
[1,3] = Field5:
[1,4] = Field7:
[1,5] = Field2:
[1,6] = Field4:
[1,7] = Field6:
}
valueSet =
{
[1,1] = 1
[1,2] = 3
[1,3] = 5
[1,4] = [7 8 9]
[1,5] = two
[1,6] = 4
[1,7] = 6
}
From the Container class doc:
mapObj = containers.Map(keySet,valueSet)

Matlab - read a specific format line

I have a file which contains data in the following format 0,"20 300 40 12".
How can I read this data with sscanf function such that I store 0 in a separate variable and 20 300 40 12 in another variable. The problem is that the array within the " " changes its size, so I cannot use a fix length array. So I can have something like this within my file:
0,"20 300 40 12"
0,"20 300 43 40 12"
1,"22 40 12"
Can you give me a hint of how to read this?
Have you tried with this:
fid = fopen(filename,'r');
A = textscan(fid,'%d,%q','Delimiter','\n');
Here's another way to do it:
[a,b] = textread('ah.txt','%d,"%[^"]"');
fun = #(x) split(' ',x);
resb = cellfun(fun,b,'UniformOutput',false)
res = {a resb};
function l = split(d,s)
%split string s on string d
out = textscan(s,'%s','delimiter',d,'multipleDelimsAsOne',1);
l = out{1};