Struggling to vertically append a string ( csv file) to an existing matrix in Scilab/matlab - matlab

M=read_csv("Gradesheets\MECN2073_2014.csv")
disp(size(M,1))
for x=1:1:size(M,1)
StudNum=M(x,1)
Grd=M(x,2) // Grd is grade column in gradesheets hence x,2 (column 2 of Grd )
if find(StudNum==StudentNumbers)>0 then disp("Exists")
H = [StudNum]
StudentNumbers = [StudentNumbers;StudNum]
end
end
This is where i get error:
Undefined operation for the given operands.
check or define function %s_f_c for overloading.
at line 38 of exec file called by :

I assume that StudentNumbers is the vector containing all your existing students right? If so, try the code below and let me know what you get.
M=read_csv("Gradesheets\MECN2073_2014.csv")
storing = [];
for i=1:size(M,1)
StudNum=M(i,1)
if find(StudNum==StudentNumbers(i)) == 1
disp("Exists");
storing = [storing;StudNum];
end
end

Related

What is the best practice to recursively extract data from a nested structure in matlab?

I'm trying to exctract some data from a nested structure in a recursive manner. First, I know that this has a field (values) which repeats itself inside the nested structure. Secondly I know that the structure which has those values has only structures as fields. In the below code I've tried to acces the structure.values by searching if my current structure has a field named values. If it has, I put .values at the end of my structure name. If it doesn't have this field, I verify if all the fields are structures. If they are, it means that I will have to consider them further and to extract the values from each one. If the fields are not structures, it means that they are values and I save them into a new simplified structure. Example of fields that I want: S.values.model1.values.mission.values.(alt/list). Currently, with the below code I'm only able to get the values from one field and then I get an error and don't know how to approach further.
Code example:
clear all
clc
S=struct()
S.case='1';
S.type='A';
S.values.model1.case='2'
S.values.model1.type='C'
S.values.model1.values.mission.case='3'
S.values.model1.values.mission.type='D'
S.values.model1.values.mission.values.alt='none'
S.values.model1.values.mission.values.list=2
S.values.model1.values.mission.values.parameter=4
S.values.model1.values.phase.case='4'
S.values.model1.values.phase.type='A'
S.values.model1.values.phase.values.num='all'
S.values.model1.values.phase.values.eq=2
S.values.model1.values.phase.values.unit=4
S.values.model1.values.analysis.case='1'
S.values.model1.values.phase.type='A'
S.values.model1.values.phase.values.nump1.list='all'
S.values.model1.values.phase.values.nump1.table='four'
S.values.model1.values.phase.values.nump1.mean=0
S.values.model1.values.phase.values.nump2.list='none'
S.values.model1.values.phase.values.nump2.table='three';
S.values.model1.values.phase.values.nump2.mean=1
s=S.values.model1;
names=fieldnames(s);
nnames=numel(names);
newStruct={};
[valsi,newstructi]=extractValues(names,s,nnames,newStruct)
function [vals,newStruct]=extractValues(names,vals,nnames,newStruct)
if any(strcmp(names,'values'))
vals=vals.('values');
names=fieldnames(vals)
nnames=numel(names)
[vals,newStruct]=extractValues(names,vals,nnames,newStruct);
end
for j=1:nnames
value(j)=isstruct((vals.(names{j})));
end
if all(value)
for k=1:nnames
vals=(vals.(names{k}));
names=fieldnames(vals);
nnames=numel(names);
[vals,newStruct]=extractValues(names,vals,nnames,newStruct);
end
else
for j=1:nnames
value=(vals.(names{j}));
newStruct.(names{j})=value;
end
end
end
As it is known beforehand what fields are requested you can arrange the subsequent filed names in a cell array and use a loop to extract the value:
names = {'values', 'model1', 'values', 'mission', 'values', 'alt'};
out = S;
for name : names
out = out.(name{1});
end
So that is a loop version of using:
out = S.values.model1.values.mission.values.alt;
EDIT:
If you want to list all field names and all field values you can used these functions:
function out = names(s, p)
if isstruct(s)
out = {};
f = fieldnames(s);
for i = 1:numel(f)
s1 = s.(f{i});
p1 = [p '.' f{i}];
out = [out; names(s1, p1)];
end
else
out = {p};
end
end
function out = values(s)
if isstruct(s)
out = {};
f = fieldnames(s);
for i = 1:numel(f)
out = [out; values(s.(f{i}))];
end
else
out = {s};
end
end
Use them as:
n = names(S, 'S');
v = values(S);

Matlab; Structure field name with valuable ( = number)

I am trying to assign valuable, which is number and given by for loop, to the name of structure field. For example, I would like to do as following,
A.bx, where A is name of structure(= char), b is part of field name ( = char) and x is valuable given by for loop. A and b is fixed or predefined.
Any comment is appreciated !
genvarname(str,list) generates a valid variable name in str [a string] in which at each iteration value in str is different from the exclusion list
And fieldname(S) returns a list of all the names of the field already in the structure S (use it to create a exclusion list)
Here is a code for what you want:
A = struct ();
for i = 1:5
A.(genvarname ('b', fieldnames (A))) = i;
end
Read about 1. genvarname(str,list) 2. fieldnames(S)
You can name you struct fields using simple sprintf
A = struct()
for ii = 1:10
fn = sprintf('b%d', ii );
A.(fn) = ii; % use the struct
end
I tend to agree with sebastian that suggested using arrays or cells over this type of field naming. In addition to cells and arrays you might find containers.Map to be very versatile and useful.

Access data in structures when field names are unknown

I have data as a struct with several layers, for example:
data.A.B
The data I want to access is in layer B. But the problem is that field names in B can be different depending on where the data comes from. Therefore I can't just type:
data.A.B.myData
myData is itself a struct
I can use:
fieldnames(data.A)
to find the names, but this doesn't help my much. I would have to write code sections for every possible field name that can occur at this level. And that's just what i trying to avoid.
Is there a way to get down to the data I have (myData) without knowing the field names of B?
Traditionally, you can loop over the fieldnames and perform the search of myData at a specific sub-structure of the struct. However, if you don't know which sub-structure you need to search, then you can perform a recursive algorithm. Below is an example. It will return the first match of myData in the struct or an empty matrix if no match found. The code can be improved to find all matches of myData.
function S2=getmyfield(S1,queriedField)
if isstruct(S1)
% Get all fieldnames of S1
fieldArray=fieldnames(S1);
% Find any match with the queried field. You can also use isfield().
% If there is a match return the value of S1.(queriedField),
% else perform a loop and recurse this function.
matchTF=strcmp(queriedField,fieldArray);
if any(matchTF)
S2=S1.(fieldArray{matchTF});
return;
else
S2=[];
i=0; % an iterator count
while isempty(S2)
i=i+1;
S2=getmyfield(S1.(fieldArray{i}),queriedField);
end
end
else
S2=[];
end
end
Cheers.
You just need a recursive function that checks fieldnames at each level for the structure.
This is roughly what you need (it could be improved to supply the path to the found field).
function [ value, found ] = FindField( rootStruct, fieldName )
%FindField - Find a field with a structure
value = [];
found = 0;
if isstruct( rootStruct )
fields = fieldnames(rootStruct);
for fi=1:length(fields)
if strcmp(fields{fi}, fieldName )
value = rootStruct.(fieldName);
found = true;
return;
end
[value, found ] = FindField( rootStruct.(fields{fi}), fieldName );
if found
return;
end
end
end
end
Usage example:
a.b = 1;
a.b.c = 2;
a.b.d = struct('Index',1,'Special',2);
FindField(a,'d')
ans =
Index: 1
Special: 2

fortran, read command

I have a .dat file that I want to read with a program in Fortran 90. The data file contains only one very long column of complex numbers. My problem is that I want to read only one part of the column, e.g., only from the nth up to the mth element including, and create an one-dimensional array from it. However, if I write something like
open(unit = 100, file = 'datafile.dat', status = 'old', action = 'read')
do j = n,m
read(100,*) vec(j-n+1)
end do
close(100)
the program reads the first m-n+1 elements from my file and not the ones from n to m including. Is there any way to do what I want?
Well, there is an obvious solution - you can simply execute n-1 dummy reads before reading actual data:
open(unit = 100, file = 'datafile.dat', status = 'old', action = 'read')
do j = 1,n-1
read(100,*)
end do
do j = n,m
read(100,*) vec(j-n+1)
end do
close(100)
You can also use the / edit descriptor and condense the first loop into a single read statement:
nm2 = n-2
read(100,'(<nm2>/)')
do j = n,m
read(100,*) vec(j-n+1)
end do
(this is n-2 records are being skipped because of the <nm2>/ edit descriptor and one record is skipped by the dummy read)
With compilers that do not support the <x> format extension, you can construct the format descriptor in an internal file:
character(len=20) :: fmt
write(fmt, "('(',I0,'/)')") n-2
read(100,fmt)
do j = n,m
read(100,*) vec(j-n+1)
end do

MATLAB: Using the If statement with a string to return values from other arrays

I have a matlab program where I am importing some arrays from excel. I am trying to write an if statement that looks in the first array, say:
Thing-1 Thing-1 Thing-3 Thing-5
If a column is a "Thing-1", then it goes to a different array, and calculates 3 values that are to be given different variable names...any guidance would be much appreciated! Thanks!
You need a function like vlookup as in Excel.
I have written one. Here is the source code:
function [content, index] = vlookup(m, e, column, lookcolumn)
if isempty(m) || isempty(e), return; end
if nargin <= 3, lookcolumn = 1; end
isechar = ischar(e);
assert(isechar || isnumeric(e), 'the second parameter must be a string or numeric');
if iscell(m)
content = {}; index = [];
if isechar
index = find(strcmp(e, m(:, lookcolumn)));
content = m(index, column);
else
for i = 1:size(m, 1)
if isnumeric(m{i, lookcolumn}) && m{i, lookcolumn} == e
content = [content; m(i, column)]; %#ok<*AGROW>
index = [index; i];
end
end
end
else
assert(~isechar, 'When the first para is a matrix, the second para must be numeric');
index = find(m(:, lookcolumn) == e);
content = m(index, column);
end
The question is... not very clear, but let me try and give you some suggestions.
Say you read some data from an Excel workbook in which the first row is headers, followed by lots of rows with numbers.
[num,txt] = xlsread(excelFileName);
so that num contains the numeric data and txt the string column headers.
Then you can check for the string Thing-1 in the column headers. thingOneIdx is an array with indices into the columns of the header. In your example, it would be [1 2], since the first two columns are Thing-1.
thingOneIdx = find(strcmp('Thing-1',txt));
You can create three cell arrays, firstValue, secondValue, and thirdValue that will store the results of the three calculations. If you need to keep the Thing-1 data around in an additional array, you can do that analogously.
%# define cell arrays (do it in one go using deal)
[firstValue,secondValue,thirdValue] = deal(cell(length(thingOneIdx),1));
%# for simplicity and readability, loop through isThingOneIdx to assign data
for ct = 1:length(thingOneIdx)
myIdx = thingOneIdx(ct);
firstValue{ct} = someCalculation(num(myIdx,:));
secondValue{ct} = someOtherCalculation(num(myIdx,:));
%# etc
end