Cannot find string in table matlab - matlab

Writing in Matlab
I am trying to find this string "+972 52-697-8081" in a the table namesnumbers as can be seen in the picture,it exists in the table though it returns 0 in the specific place where it exists.the line i used is
IndexC = strfind(namesnumbers{:,:},string(newnum) );
When i tried contains not a variable it did find the index though as a specific number
IndexC = strfind(namesnumbers{:,:},"+972 52-697-8081" );
What am I doing wrong?
link to the excel
sheets:https://www.transfernow.net/dl/202107194gVG4laZ/ej6NSpdd
the code:
finalnames=readtable("names1example.xlsx");
m1="101.xlsx";
t=readtable(m1);
m=t(4:end,:);
[size1,~]=size(t);
numbers=t(:,3);
namesnumbers=finalnames(:,3);
for k=3:size1
number= numbers{k,1};
IndexC = strfind(namesnumbers{:,:},string(number) );
Index = find(not(cellfun('isempty',IndexC)));
gender=finalnames(Index,2);
name=finalnames(Index,1);
end
t(:,4)= (name);
t(:,5)= (gender);
t(:,6:end)=m;
m2=append("H",m1);
writetable(t,m2);

There is no need to use strfind with tables for what you're trying to do.
The quick example bellow should give you an indication how to extract a single or multiple rows from your table.
% example table from MATLAB doc
T = table(categorical({'M';'F';'M'}),[45;32;34],...
{'NY';'CA';'MA'},logical([1;0;0]),...
'VariableNames',{'Gender','Age','State','Vote'})
% get the row that matches the string "NY"
T(T.State == "NY",:)
% get the rows where the state matches any of the given set
setOfStates = ["NY", "CA", "CAN"];
T(ismember(T.State,setOfStates),:)

Related

All tables in the bracketed expression must have the same variable names

I have two editable numeric fields and a table in app designer; the user can enter the values in these editable fields and then push a button. Then, the values are added to a table. Also, I provide an option to attach an excel folder that should have two columns to reflect on the table.
Both of these work perfectly fine individually, but, if I added the values manually then attached an excel folder or vice versa, I get the following error: All tables in the bracketed expression must have the same variable names.
The function that handles the editable fields:
app.t = app.UITable.Data;
x = app.xvalueEditField.Value;
y = app.yvalueEditField.Value;
nr = table(x, y);
app.UITable.Data = [app.t; nr]; %% error happens here if I attach excel then add manually
app.t = app.UITable.Data;
The Function of the excel folder:
text = readtable([pathname filename], "Sheet",1, 'ReadVariableNames',false);
fl = cellfun(#isnumeric,table2cell(text(1,:)));
if (numel(fl(fl == false)) > 0)
flag = false;
else
flag = true;
end
if (flag)
A = [app.t; text]; %% error happens here if I add manually then attach
app.UITable.Data = A;
app.t = text;
end
Note: these are only the parts of the function, where I attempt to combine values
Can someone please help me?
Thank you
The error message is telling you that table only allows you to vertically concatenate tables when the 'VariableNames' properties match. This is documented here: https://www.mathworks.com/help/matlab/ref/vertcat.html#btxzag0-1 .
In your first code example, the table nr will have variable names x and y (derived from the names of the underlying variables you used to construct the table). You could fix that case by doing:
% force nr to have the same VariableNames as app.t:
nr = table(x, y, 'VariableNames', app.t.Properties.VariableNames);
and in the second case, you can force text to have the correct variable names like this:
text.Properties.VariableNames = app.t.Properties.VariableNames

Left Join tables in MATLAB

I tried to find something relevant but to no avail, except this post which I can't say it was helpful.
I have two tables A and B:
A has dimensions 5x5 and non unique values in the LastName
LastName = {'Smith';'Johnson';'Williams';'Smith';'Williams'};
YearNow= [2010;2010;2010;2010;2010];
Height = [71;69;64;67;64];
Weight = [176;163;131;133;119];
BloodPressure = [124; 109; 125; 117; 122];
A = table(LastName,YearNow,Height,Weight,BloodPressure);
and B has dimensions 3x2 and unique values in LastName
LastName = {'Smith';'Johnson';'Williams'};
YearBorn= [1950;1975;1965];
B = table(LastName,YearBorn);
I want to create a new column on Table A that will contain their age after I subtract for each A.YearNow the B.YearBorn, so the last column will have the form
A.Age = [60,35,45,60,45];
When I try to use [detect,pos] = ismember(A,B(:,1)); I get an error:
A and B must contain the same variables.
Any help would be appreciated.
Instead of using ismember, which can be quite error-prone as you have to put things in the right order, you could also use Matlab's outerjoin instead:
A = outerjoin(A,B,'Type','Left','MergeKeys',true);
A.Age = A.YearNow - A.YearBorn;
Note that outerjoin modifies the ordering. See the official Matlab documentation for all the input arguments.
An additional advantage of outerjoin over ismember is that in case not all LastNames in table A exist in table B, you will have to pre-allocate output with ismember, and use the first output argument as well.
You need to extract the LastName columns and pass them to ismember. Then you can use the index vector it returns to compute the Age column as follows:
[~, index] = ismember(A.LastName, B.LastName);
A.Age = A.YearNow-B.YearBorn(index);

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'

Make a MatLab table out of 2 Cell Array

What is the most efficient way to generate a table from 2 cell arrays. Array A contains data and Array B contains the corresponding names. I would like to combine them into a convenient table structure.
Cell_Array_A =
{[10x10],[10x10],[];
[10x11],[],[10x12];
[9x10],[13x10],[]}
Cell_Array_B =
{['A','B',[];
'B',[],'A';
'B','A',[]}
It should generate a table with the headers 'A' and 'B'. However, in my real data set, I have a lot of variable names, which I don't know. So I need a way to read all variables from the first row and use them to create the table for the rest of the matrix.
Example of the desired output:
'A' 'B'
[10x10] [10x10]
[10x12] [10x11]
[13x10] [9x10]
I tried so far to process the arrays row wise to get rid of the empty arrays. However this is not very efficient. I run the following code for each row in Array A and B. Below an example for the first row in Array A which I later on use as the tablet for my table.
order_row = {};
order_row = Cell_Array_A(1,:);
ordered_filenames = order_row(~cellfun('isempty',order_row));
Edited answer The idea is 1) to collect the non-empty column headers, 2) for each unique column header collect the corresponding values:
% Unique variable names
nul_names = cellfun(#isempty,Cell_Array_B);
var_names = unique(Cell_Array_B(~nul_names));
% Function to find a column header index
ixhead = #(h,c) cellfun(#(x) isequaln(x,h), c(:));
% Collect the values
var_values = cellfun( ...
#(h) Cell_Array_A(ixhead(h, Cell_Array_B)), var_names, ...
'UniformOutput', false ...
);
% Create the table
tbl = table(var_values{:}, 'VariableNames', var_names);

Best way to select from several LUTs? (Modelica)

In our model of a physical system, we modify one flux value by a factor from a look-up table. The LUT itself is selected from a catalog of LUTs based on an integer index. We're currently loading the table data into CombiTable2D components. What is the correct way to select/define the correct LUT? If we have them all as named tables in one input data file, is there a way to pick an LUT based on it's tableName (the CombiTable parameter)? I've been playing with For loops in either equation or algorithm formats, but haven't found a syntax that works yet.
Thanks in advance for the thoughts...
I think it only works with one table per file so you can have an array of tables, something like:
parameter Integer N = 3;
parameter String selectTable = "tab2";
Modelica.Blocks.Tables.CombiTable2D tableArray[N](
each tableOnFile = true,
fileName = {"file1", "file2", "file3"},
tableName={"tab1", "tab2", "tab3"});
// use the tableArray
for i in 1:N loop
// note that N and selectTable need to be known at compile
// time so that the if and the for loop can be expanded
if (tableArray[i].tableName == selectTable)
then
connect(tableArray[i].u1, u1);
connect(tableArray[i].u2, u2);
connect(tableArray[i].y, y);
endif;
end for;