MatLab Map - Specified Key Type Not Matching Required - matlab

I'm attempting to make a program (for homework) which reads in a file, and then counts the number of times each word is used. For tackling the issue efficiently, I've decided to map all unique words to keys, and then increment the key value each time the word comes up.
function [] = problem2
file_open = fopen('austen.txt');
complete_string = textscan(file_open, '%s');
numel(complete_string{1,1})
unique_words = unique(complete_string{1,1});
length(unique_words);
frequency = zeros(numel(unique_words), 1);
found_frequency = containers.Map(unique_words, frequency);
for i=1:numel(complete_string{1,1})
found_frequency(complete_string{1,1}(i)) = found_frequency(complete_string{1,1}(i))+1;
end
fclose(file_open)
Sadly, this code does not work. When the line comes up to increment, I receive an error stating that "specified key type does not match the type expected for this container", which makes no sense to me - I'm using strings as the keys. Any ideas as to why I'm receiving this error?

The issue was in the use of Cell type - complete_String{1,1}(i) would actually return a Cell rather than a String (per spec, though). Wrapped it in char(*) and it worked fine.

Related

How to use pattern matching callbacks in Dash for Julia

I'm new to julia, but not so new on Dash; I'm trying to build my first app with Dash for julia, but I can't seem to make a pattern matching callback work properly. Here's the part of the code that's giving me troubles:
callback!(
app,
Output((type= "filter_", index= ALL), "options"),
Input("inputs", "data"),
State((type= "filter_", index= ALL), "value"),
) do inputs, filters
list_outs = []
list_vals = []
for i in 1:length(filters)
push!(list_outs, [(label= input, value= input) for input in inputs])
end
return list_outs
end
What I'm trying to do here is to use the available inputs of the data set, already stored in "inputs", to set the filters' options, creating as many sets of options as there are dropdowns.
The problem here is, I guess, in the format of the output I'm returning: it says "Invalid number of output values for {"index":["ALL"],"type":"filter_"}.options. Expected 3, got 1"
Sadly, I found nothing of use about how to use pattern matching callbacks with julia; I tried passing the output both as an array and as a tuple, but to no avail.
Any help is welcomed, thank you all!
This is the error related to the fact that if the result is a single Output, the callback output is automatically represented as an array of what is returned for uniform further processing. I.e., in your case, as [list_outs]. The fact that the Output with the match pattern is also treated as a single one is my bug, I added the issue and try to fix it in the near future.
Right now you can work around this problem by using Output as an array:
using Dash
using DashHtmlComponents
using DashCoreComponents
app = dash()
app.layout = html_div() do
dcc_input(id = "input", value = "A,B,C"),
dcc_dropdown(id = (type="filter_", index = 1)),
dcc_dropdown(id = (type="filter_", index = 2)),
dcc_dropdown(id = (type="filter_", index = 3)),
dcc_dropdown(id = (type="filter_", index = 4))
end
callback!(
app,
[Output((type= "filter_", index= ALL), "options")], #This is multiple output in explicitly form
Input("input", "value"),
State((type= "filter_", index= ALL), "value"),
) do input, filters
inputs = split(input, ",")
list_outs = []
list_vals = []
for i in 1:length(filters)
push!(list_outs, [(label= input, value= input) for input in inputs])
end
return [list_outs] # Accordingly, we return the result inside an additional array
end
run_server(app, debug = true)

Numerical values associated with Drop Down options

So I am creating an app to work out a value based on a series of variables. The variables are:
Gender
Age
Weight
Creatinine
Here's what the app looks like:
In order to simplify the process somewhat I decided to make the gender selection a dropdown menu, this has caused me some issues since I have it setup like so:
And the maths associated with the button looks like so:
function CalculateButtonPushed(app, event)
gender = app.PatientGenderDropDown.Value ;
age = app.PatientAgeEditField.Value ;
weight = app.LeanBodyWeightEditField.Value ;
serum = app.SerumCreatinineEditField.Value ;
final = (gender*(age)*weight) / (serum) ;
app.ResultEditField.Value = final ;
end
end
Running this gives the following error:
Error using
matlab.ui.control.internal.model.AbstractNumericComponent/set.Value
(line 104) 'Value' must be numeric, such as 10.
As far as I am aware, the values I input into ItemsData are numeric values. Have I missed something or is there a better way to do this?
If you put a breakpoint in the offending file on the appropriate line (by running the below code),
dbstop in uicomponents\+matlab\+ui\+control\+internal\+model\AbstractNumericComponent.m at 87
you could see the following in your workspace, after clicking the button:
There are two separate problems here, both of which can be identified by looking at the newValue validation code (appearing in AbstractNumericComponent.m):
% newValue should be a numeric value.
% NaN, Inf, empty are not accepted
validateattributes(...
newValue, ...
{'numeric'}, ...
{'scalar', 'real', 'nonempty'} ...
);
Here are the issues:
The new value is a vector of NaN.
The reason for this is in this line:
final = (gender*(age)*weight) / (serum) ;
where serum has a value of 0 - so this is the first thing you should take care of.
The new value is a vector of NaN.
This is a separate problem, since the set.Value function (which is implicitly called when you assign something into the Value field), is expecting a scalar. This happens because gender is a 1x4 char array - so it's treated as 4 separate numbers (i.e. the assumption about ItemsData being a numeric is incorrect). The simplest solution in this case would be to str2double it before use. Alternatively, store the data in another location
(such as a private attribute of the figure), making sure it's numeric.

Read specific portions of an excel file based on string values in MATLAB

I have an excel file and I need to read it based on string values in the 4th column. I have written the following but it does not work properly:
[num,txt,raw] = xlsread('Coordinates','Centerville');
zn={};
ctr=0;
for i = 3:size(raw,1)
tf = strcmp(char(raw{i,4}),char(raw{i-1,4}));
if tf == 0
ctr = ctr+1;
end
zn{ctr}=raw{i,4};
end
data=zeros(1,10); % 10 corresponds to the number of columns I want to read (herein, columns 'J' to 'S')
ctr=0;
for j = 1:length(zn)
for i=3:size(raw,1)
tf=strcmp(char(raw{i,4}),char(zn{j}));
if tf==1
ctr=ctr+1;
data(ctr,:,j)=num(i-2,10:19);
end
end
end
It gives me a "15129x10x22 double" thing and when I try to open it I get the message "Cannot display summaries of variables with more than 524288 elements". It might be obvious but what I am trying to get as the output is 'N = length(zn)' number of matrices which represent the data for different strings in the 4th column (so I probably need a struct; I just don't know how to make it work). Any ideas on how I could fix this? Thanks!
Did not test it, but this should help you get going:
EDIT: corrected wrong indexing into raw vector. Also, depending on the format you might want to restrict also the rows of the raw matrix. From your question, I assume something like selector = raw(3:end,4); and data = raw(3:end,10:19); should be correct.
[~,~,raw] = xlsread('Coordinates','Centerville');
selector = raw(:,4);
data = raw(:,10:19);
[selector,~,grpidx] = unique(selector);
nGrp = numel(selector);
out = cell(nGrp,1);
for i=1:nGrp
idx = grpidx==i;
out{i} = cell2mat(data(idx,:));
end
out is the output variable. The key here is the variable grpidx that is an output of the unique function and allows you to trace back the unique values to their position in the original vector. Note that unique as I used it may change the order of the string values. If that is an issue for you, use the setOrderparameter of the unique function and set it to 'stable'

Looping through documents in matlab

I am attempting to loop through the variable 'docs' which is a cell array that holds strings, i need to make a for loop that colllects the terms in a cell array and then uses command 'lower' and unique to create a dictionary.
Here is the code i've tried sp far and i just get errors
docsLength = length(docs);
for C = 1:docsLength
list = tokenize(docs, ' .,-');
Mylist = [list;C];
end
I get these errors
Error using textscan
First input must be of type double or string.
Error in tokenize (line 3)
C = textscan(str,'%s','MultipleDelimsAsOne',1,'delimiter',delimiters);
Error in tk (line 4)
list = tokenize(docs, ' .,-');
Generically, if you get an "must be of type" error, that means you are passing the wrong sort of input to a function. In this case you should look at the point in your code where this is taking place (here, in tokenize when textscan is called), and doublecheck that the input going in is what you expect it to be.
As tokenize is not a MATLAB builtin function, unless you show us that code we can't say what those inputs should be. However, as akfaz mentioned in comments, it is likely that you want to pass docs{C} (a string) to tokenize instead of docs (a cell array). Otherwise, there's no point in having a loop as it just repeatedly passes the same input, docs, into the function.
There are additional problems with the loop:
Mylist = [list; C]; will be overwritten each loop to consist of the latest version of list plus C, which is just a number (the index of the loop). Depending on what the output of tokenize looks like, Mylist = [Mylist; list] may work but you should initialise Mylist first.
Mylist = [];
for C = 1:length(docs)
list = tokenize(docs{C}, ' .,-');
Mylist = [Mylist; list];
end

Error using minus in MATLAB

temp(i,1) = rand(1)*(pb(1,num).pos(i,1) - pw(1,num).pos(i,1));
This line gives the following error:
Error using ==> minus
Not enough input arguments.
The following are the definitions of pb and pw.
pw=struct('fitness',[],'pos',{});
pb=struct('fitness',[],'pos',{});
pos is a 2 x 1 array.
When tracking down errors like this, I break the problem up into smaller bits. Especially when the logic isn't readily apparent. Not only does it provide a path that can be used to step through your function using the debugger, but it also makes it more readable.
I've taken liberty with the intermediate variable names.
thisPb = pb(1,num);
thisPw = pw(1,num);
initialPos= pw.pos(i,1);
finalPos = pb.pos(i,1);
whos initialPos finalPos
temp(i,1) = rand(1) * (finalPos - initialPos);
The line with whos will print out the values. Make sure that finalPos and initialPos are both numbers.
One way that you can get this error is when num is an empty matrix.
The expression
>> s(x).a
can return a variable number of outputs, depending on the size of x.
If x = [1,2,3] for example, it will return three values (as long as s has at least three elements).
If x = [] on the other hand, then s(x).a will return no outputs, so the expression
>> disp(s(x).a)
will give you a Not enough input arguments error, which is almost certainly what you're seeing. You should check that num is not empty.
Are you sure, that all values are really initialised? Try to check this before your codeline.
disp(pb(1,num).pos(i,1))
disp(pw(1,num).pos(i,1))
temp(i,1) = rand(1)*(pb(1,num).pos(i,1) - pw(1,num).pos(i,1));