Write to the textbox only if the condition is true in Matlab - matlab

I struggle with printing text in my Matlab GUI.
I have code like this in my callback:
if Lia == ismember(handles.T(1:3),(1,1,1))
set(handles.t1, 'String', 'good day');
end
The problem is, I don't know how to check if in my array indexes from 1 to 3 I got this numbers: 1,1,1. I was looking to the documentation but it appears it says nothing about that (or I simply cannot find the proper answer).

You can simply use all and check to see if every element in the first three slots of your array match the values of 1 explicitly. I don't know the shape of your array so I'm going to force it to be a column vector. If the first three slots of the array was a row or column vector and if we assumed that the values of 1 are a column or row vector respectively then you're going to get a rather unpleasant surprise:
h = handles.T(1:3);
if all(h(:) == [1; 1; 1])
set(handles.t1, 'String', 'good day');
end
Note that I could have simply done all(h(:) == 1) as a special case since we are performing a comparison of every element in an array with a single value. However, I have a feeling that this may change for you, so I've decided to explicitly make a vector of 1s so you can change the contents of what you want to compare to at a later time.

Related

How to update values from rows on a matrix

I have a matrix: 6 rows x 18 columns
and I want to ask the user which row he wants to change to 0 and make it happen, but if he inputs 0 it just exits the program
row = input('Input 0 to exit\n\n Row to eliminate:', 's');
if row ~= 0
M(row,:) = 0;
disp(M)
end
I want to to change the whole input row to 0, but it somehow creates 44 more rows below the original matrix (all 0) and doesn't change the first 6 rows(original matrix)
row is a char vector, not a number. For example if you type “4”, the variable contains the character 4, which has a numeric value of 52 (ASCII code). Using that to index will create a row #52 and fill it with zeros. To make that row it needed to make the intermediate rows as well, whose values default to 0.
To solve the problem, remove the 's' from the call to input. This will cause the return value to be interpreted as a MATLAB expression, rather than directly returning the entered text as a char vector.
However, if there is a chance that your program is used by a malicious user or a stupid user, this solution is dangerous (as indicated by #Luis Mendo in a comment) because it evaluates whatever the user types, which means the user can e.g. type a command that wipes your hard drive.
A safer solution is to use str2double to convert the char array output of input to a number that you can use to index.

Build a matrix starting from instances of structure fields in MATLAB

I'm really sorry to bother so I hope it is not a silly or repetitive question.
I have been scraping a website, saving the results as a collection in MongoDB, exporting it as a JSON file and importing it in MATLAB.
At the end of the story I obtained a struct object organised
like this one in the picture.
What I'm interested in are the two last cell arrays (which can be easily converted to string arrays with string()). The first cell array is a collection of keys (think unique products) and the second cell array is a collection of values (think prices), like a dictionary. Each field is an instance of possible values for a set of this keys (think daily prices). My goal is to build a matrix made like this:
KEYS VALUES_OF_FIELD_1 VALUES_OF_FIELD2 ... VALUES_OF_FIELDn
A x x x
B x z NaN
C z x y
D NaN y x
E y x z
The main problem is that, as shown in the image and as I tried to explain in the example matrix, I don't always have a value for all the keys in every field (as you can see sometimes they are 321, other times 319 or 320 or 317) and so the key is missing from the first array. In that case I should fill the missing value with a NaN. The keys can be ordered alphabetically and are all unique.
What would you think would be the best and most scalable way to approach this problem in MATLAB?
Thank you very much for your time, I hope I explained myself clearly.
EDIT:
Both arrays are made of strings in my case, so types are not a problem (I've modified the example). The main problem is that, since the keys vary in each field, firstly I have to find all the (unique) keys in the structure, to build the rows, and then for each column (field) I have to fill the values putting NaN where the key is missing.
One thing to remember you can't simply use both strings and number in one matrix. So, if you combine them together they can be either all strings or all numbers. I think all strings will work for you.
Before make a matrix make sure that all the cells have same element.
new_matrix = horzcat(keys,values1,...valuesn);
This will provide a matrix for each row (according to your image). Now you can use a for loop to get matrices for all the rows.
For now, I've solved it by considering the longest array of keys in the structure as the complete set of keys, let's call it keys_set.
Then I've created for each field in the structure a Map object in this way:
for i=1:length(structure)
structure(i).myMap = containers.Map(structure(i).key_field, structure(i).value_field);
end
Then I've built my matrix (M) by checking every map against the keys_set array:
for i=1:length(keys_set)
for j=1:length(structure)
if isKey(structure(j).myMap,char(keys_set(i)))
M(i,j) = string(structure(j).myMap(char(keys_set(i))));
else
M(i,j) = string('MISSING');
end
end
end
This works, but it would be ideal to also be able to check that keys_set is really complete.
EDIT: I've solved my problem by using this function and building the correct set of all the possible keys:
%% Finding the maximum number of keys in all the fields
maxnk = length(structure(1).key_field);
for i=2:length(structure)
if length(structure(i).key_field) > maxnk
maxnk = length(structure(i).key_field);
end
end
%% Initialiting the matrix containing all the possibile set of keys
keys_set=string(zeros(maxnk,length(structure)));
%% Filling the matrix by putting "0" if the dimension is smaller
for i=1:length(structure)
d = length(string(structure(i).key_field));
if d == maxnk
keys_set(:,i) = string(structure(i).key_field);
else
clear tmp
tmp = [string(structure(i).key_field); string(zeros(maxnk-d,1))];
keys_set(:,i) = tmp;
end
end
%% Merging without duplication and removing the "0" element
keys_set = union_several(keys_set);
keys_set = keys_set(keys_set ~= string(0));

Mean of outlinks of a sparse matrix

So I'm working with sparse matrix and I have to find out different info about a very big one (10^6 size) and I need to find out the mean of the outlinks. Just to be sure I think mean is what you get from 3+4+5/3=4, 4 is the mean.
I thought of something like this:
[row,col] = find(A(:,2),1,'first')
and then I would do 1/numberInThatIndex or something similar, since it's a S-matrix (pretty sure it's called that).
And I would iterate column by column but for some reason it's not giving me the first number in each column, if I do find(A(:,1),1,'first') it does give me the first in the first column, but not in the second if I change it to A(:,2).
I'd also need something to store that index to access the value, I thought of a 2xN vector but I guess it's not the best idea. I mean, find is going to give me index, but I need the value in that index, and then store that or show it. Not sure if I'm explaining myself properly but I'm trying, sorry about that.
Just to be clear both when I input A(:,1) and A(:,2) it gives me index from the first column, and I do not want that, I want first element found from each column, so I can calculate the mean out of the number in that index.
edit: allright it seems like that indeed does work, but when I was checking the results I was putting 3817 instead of 3871 that was the given answer and so I found a 0 when I wanted something that's not a zero. Not sure if I should delete all of this.
To solve your problem, you can do the following:
numberNonZerosPerColumn = sum(S~=0,1);
meanValue = nanmean(1./numberNonZerosPerColumn);
Count the number of nonzero elements in every column n(i)
Compute the values v(i) that are stored there, which are defined by v(i) := 1/n(i)
Take the mean of those values where n(i) is not zero (i.e. summing all those values, where v(i) is not NaN and divide by the number of columns that contain at least one zero)
If you want to treat columns without any nonzero entry as v(i):= 0, but still use them in your mean, you can use:
numberNonZerosPerColumn = sum(S~=0,1);
meanValue = nansum(1./numberNonZerosPerColumn)/size(S,2);

if greater than matlab

I have a matrix of two columns and six rows, and want to build a second one with the following code:
for i=2
if F(:,i)<50
G(:,i) = 1
end
end
But nothing happens...
The idea was that if a value in the second column in F was less than 50, then the corresponding value in G would be 1.
Sorry for probably basic question, but no idea why this doesn't work. If I change to evaluate whether the F value ~= 50, then everything works as it should.
Thanks for any help.
Your if statement is only executed once - not once per element. While F(:,i)<50 returns an array of values, the if is either true or false; consequently, the next line is only executed once (either on all elements in G(:,i), or none of them).
For example, see this piece of code:
if(1 < [0 1 2]), disp('true'); end
It will produce no output, even though it is true for the third element. On the other hand,
if(1 < [2 3 4]), disp('true'); end
does produce output...
In general, the following:
1 < [0 1 2]
produces
0 0 1
Not sure why you say it doesn't work for < but it does work for ~=. Maybe there are no elements equal to 50, so it only "seems" to work?
In general, there is a better way to do what you want, with a single line:
G(F(:,2)<50,2)=1
This uses "logical indexing", and is much faster than looping. It will consider each element of F(:,2), and modify the corresponding element in G.
One final comment: it is not great practice to use the variable i since it has a built in value of sqrt(-1). If you have code anywhere that relies on it having that value, then accidentally overwriting it with any other value would break that. It's not the problem with your code today - but why set yourself up for a problem in the future.

Using ismember() with cell arrays containing vectors

I am using a cell array to contain 1x2 vectors of grid locations in the form [row, col].
I would like to check if another grid location is included in this cell array.
Unfortunately, my current code results in an error, and I cannot quite understand why:
in_range = ismember( 1, ismember({[player.row, player.col]}, proximity(:,1)) );
where player.row and player.col are integers, and proximity's first column is the aforementioned cell array of grid locations
the error I am receiving is:
??? Error using ==> cell.ismember at 28
Input must be cell arrays of strings.
Unfortunately, I have not been able to find any information regarding using ismember() in this fashion, only with cell arrays as strings or with single integers in each cell rather than vectors.
I have considered converting using num2str() and str2num(), but since I must perform calculations between the conversions, and due to the number of iterations the code will be looped for (10,000 loops, 4 conversions per loop), this method seems prohibitive.
Any help here would be greatly appreciated, thank you
EDIT: Why does ismember() return this error? Does it treat all vectors in a cell array as string arrays?
EDIT: Would there be a better / more efficient method of determining if a 1 is in the returned vector than
ismember( 1, ismember(...))?
I'm short of time at the moment (being Chrissy eve and all), so this is going to have to be a very quick answer.
As I understand it, the problem is to find if an x y coordinate lies in a sequence of many x y coordinates, and if so, the index of where it lies. If this is the case, and if you're interested in efficiency, then it is wasteful to mess around with strings or cell arrays. You should be using numeric matrices/vectors for this.
So, my suggestion: Convert the first row of your cell array to a numeric matrix. Then, compare your x y coordinates to the rows of this numerical matrix. Because you only want to know when both coordinates match a row of the numerical matrix, use the 'rows' option of ismember - it will return a true only on matching an entire row rather than matching a single element.
Some example code that will hopefully help follows:
%# Build an example cell array with coordinates in the first column, and random strings in the second column
CellOfLoc = {[1 2], 'hello'; [3 4], 'world'; [5 6], '!'};
%# Convert the first column of the cell array to a numerical matrix
MatOfLoc = cell2mat(CellOfLoc(:, 1));
%# Build an example x y coordinate location to test
LocToTest = [5 6];
%# Call ismember, being sure to use the rows option
Index = ismember(MatOfLoc, LocToTest, 'rows');
Note, if the indices in your cell array are in string form, then obviously you'll also need a call to str2num in there somewhere before you call ismember.
One other thing, I notice you're a new member, so welcome to the site. If you think this response satisfactorily answered your question, then please mark the question answered by clicking the tick mark next to this response.