Store strings in a loop into an array? - arrays

I am working in MATLAB and currently have this code:
for i =1:142674:loop_end
data = textread('Results.txt', '%s');
name = data{i};
end
However, I want the name of the data point I select to be stored into an Array where the first name would be the first string in the array and so forth. So at the end I have an array containing all the names gathered from the loop.

What about this:
counter = 0
for i =1:142674:loop_end
counter = counter + 1;
data = textread('Results.txt', '%s');
myArray{counter} = data{i};
end
myArray will contain the names.
> myarray = 'Name1' 'Name2' 'Name3' 'Name4'
Though, it will actually be a Cell array, not a regular array

Why to read the text file multiple times ?
data = textread('Results.txt', '%s');
names = data(1:142674:end);
This way names is a cell array containing 1st, 142675th, etc... strings in the file.
NB: Well maybe I've misunderstood the question.

Related

MATLAB: How to tabulate structs with same fields

I have use a 428×1 cell array called data
data = {[1×1 struct]
[1×1 struct]
....
[1x1 struct]}
These struct all have the same structure
data {2,1}
>>struct with fields
additional_model_information: 'H Series,S3150-S0-AW-04-02-C-F421,'
ceiling_fan_size_diameters_in_inches: '60'
airflow_efficiency_cfm_watt_low: '727'
airflow_efficiency_cfm_watt_high: '392'
The structure fields are the same for all 428 cells, and the fields values change in each struct.
How could i create a table that puts all of the structs together so that it shows all of the field values for each field? Pehaps using a nested for loop?
I eventually want to export this data to excel.
Let's say you've got your nx1 cell array of structs, data. This method doesn't assume you have 4 fields in your data or any knowledge of what they are called. You could even use it with structs with different fieldnames if you included some try/catch logic.
You can get the field names of a representative struct using fieldnames
fnames = fieldnames(data{1});
Then set up some output cell array out of the correct size
out = cell(numel(fnames), numel(data));
Then use nested loops to 1. loop through items in data and 2. loop through field names.
for n = 1:numel(data)
for field = 1:numel(fnames)
temp = data{n};
out{field, n} = temp.(fnames{field});
end
end
Finally, append the field names as the first column
out = [fnames, out];
And write the cell array to your Excel file
% File location, cell array, sheet, cell
xlswrite('C:\...\test.xlsx', out, 1, 'A1');
How about
T = cell(length(data) , 4);
for k = 1 : length(data)
T(k , :) = {data{k}.additional_model_information , ...
data{k}.ceiling_fan_size_diameters_in_inches, ...
data{k}.airflow_efficiency_cfm_watt_low, ...
data{k}.airflow_efficiency_cfm_watt_high};
end
Then you can use xlswrite to export to excel.

How to extract struct element name given part of the name?

I am currently post-processing a lot of .mat files (300+) created with a long simulation (3days+).
Each of these mat files contain several variables, each named after their position on a grid (yes, they've been created with eval).
I thus created a script that opens each of the files sequentially
s = what(pwd);
s = s.mat;
for i=1:length(s)
data = open(sprintf('%s',s{i,:}));
% here goes what I would like to do
end
What I am trying to do now is to extract the current name of the data component that fits a certain pattern.
Specifically, I know that in data there is a vector named coef_%i_%i and I would like to isolate it and assign it to a multi-dimensional array.
The second part I know how to do it, I can scan the variable name for the _ characters, isolate the integers and assign the vector to its appropriate location in the array.
My question is:
Is there in matlab a way to do something along the lines of vectorname = extractname('data.coef*');?
Assuming you have something like:
clear data
% create a dummy field
name = sprintf ( 'coef_%i_%i', randi(100,[2 1]) );
% a data struct with a field which starts "coef*"
data.(name) = rand;
% and your data field may contain some other fields?
data.other = [];
You can then extract out the fields which contain the coef string
function output = extractname ( data )
%extract the fieldnames from data:
fn = fieldnames(data);
% find all that have coef in them
index = cellfun(#isempty, strfind(fn,'coef'));
% remove any that dont have coef in them
fn(index) = [];
%You are then left with one(or more) that contain coef in the name:
output = fn;
end
If your data struct contains fields which may have "coef" elsewhere in the name you would need to go through them and check if coef is at the start. You should also check that at the end of your function that one and only one field has been found.

How to create a new group of character array in matlab?

I have data stored in text files.The data is in 'cell array of string' after read it using textscan and contains various of colour name. Below is the content of my data:
name of colour
'lavender'
'lavenderblush'
'lemonchiffon'
'lightblue'
'lightcoral'
'lightcyan'
I want to create new array to group all color characters into the main color only (red, blue, orange, brown,etc).
I am really struggling to solve this problem. Thank you in advance for any help.
load_data = fopen('result.txt', 'r');
C = textscan(load_data, ' %s ');
fclose(load_data);
name = C{1,1};
group = char(name)
if group{:,1} == lavender
fprintf('purple');
else
fprintf('nothing');
end
This is my code but if I run this, always get error
Cell contents reference from a non-cell array object.
From your comment above, I assume you're having trouble with your code, not actually with the sorting of colors, or how to categorize them.
group is not a Cell array, it's a Char array. So in order to access its values you should use group(:,1) instead of group{:,1}
Remember that the number of columns in group is the number of characters in that line, normalized to the number of characters of the largest string in that set. So 2 issues here:
You can't use group(:,1), as it will get the first character of all the strings in that array. You should get the entire line for that string group(1,:). NB: I say string for simplicity, it's actually a char array.
'lavender' has only 10 characters, but it will have 15, as per the largest string. So the string comparison doesn't quite work, unless you add the extra blank spaces to compensate
You can try out the code below:
load_data = fopen('result.txt', 'r');
C = textscan(load_data, ' %s ');
fclose(load_data);
name = C{1,1};
if name{1,:} == '''lavender'''
fprintf('purple');
else
fprintf('nothing');
end
I assume that your TXT file actually has the string 'lavender', in this case I used character escape '''lavender'''.
The error you are getting is fairly clear. Once you have called char(name), you are working with a regular character array (i.e. a string) and no longer a cell array. Braces (i.e. {}) are used to index cell arrays so you should instead be using parentheses (i.e. ()). Note this actually happens as soon as you index using {} so C{1,1} would actually return a string already and the char line is thus redundant:
if group(:,1) == lavender
I suspect you actually want something more like
name = C{1};
group = char(name) %this line is redundant because C{1} already extracts a string
if strcmp(group,lavender)
fprintf('purple');
else
fprintf('nothing');
end
but it's impossible to say since you did not define the variable lavender.
I would also question what data structure you intend to use. I'm going to assume you actually have some way of categorizing the colours? I'm going to assume this is manual in which case I would suggest converting your txt file to a csv file and putting your manual colour categories as a second column but I'll leave the implementation details to you.
Lets say you have 3 colour categories for now, 'purple', 'blue', and 'orange', my suggestion is to use a logical matrix that has 3 columns (1 per colour category) and n rows where n is the number of rows in your text file (i.e. the number of colours you need to categorize).
Now I'm going to assume you have some sort of mapping function that can categorize your colours so map('lavender') returns 'purple' and map('lightcyan') returns 'blue'
First we should make a cell array of categories that we can use to map the category string to its column number:
categories = {'purple'
'blue'
'orange'}
and the result will go in the logical matrix categorized
load_data = fopen('result.txt', 'r');
C = textscan(load_data, ' %s ');
fclose(load_data);
n = numel(C);
categories = {'purple'
'blue'
'orange'};
categorized = false(n, numel(categories)); %preallocation
for row = 1:n
colour = C{row};
category = map(colour); %you need to implement this map function yourself.
categorized(row, strcmp(category, categories)) = true;
end

How to name variables in a data array using a for loop

I have an array within an array and I am trying to name the variables using a for loop as there are a lot of variables. When I use the following simple code Time1 = dataCOMB{1,1}{1,1}(1:1024, 1); it opens the first cell in an array and proceeds to open the first cell in the following array and finally defines all the values in column 1 rows 1 to 1024 as Time1. However I have 38 of these different sets of data and when I apply the following code:
for t = 1:38
for aa = 1:38
Time(t) = dataCOMB{1,1}{1,aa}(1:1024, 1);
end
end
I get an error
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in Load_Files_working (line 39)
Time(t) = dataCOMB{1,1}{1,aa}(1:1024, 1);
Basically I am trying to get matlab to call the first column in each data set Time1, Time2, etc.
The problem:
1)You'd want to extract in a cell row...
2) ...the first 1024 numbers in the 1st column...
3) ...from each of the first 38 cells of a cell array.
The plan:
1) If one wants to get info from each element of a cell array (that is, an array accessed via {} indexing), one may use cellfun. Calling cellfun(some_function, a_cell_array) will aggregate the results of some_function(a_cell_array{k}) for all possible k subscripts. If the results are heterogeneous (i.e. not having the same type and size), one may use the cell_fun(..., 'UniformOutput', false) option to put them in an output cell array (cell arrays are good at grouping together heterogeneous data).
2) To extract the first 1024 numbers from the first column of an numeric array x one may use this anonymous function: #(x) x(1:1024,1). The x argument will com from each element of a cell array, and our anonymous function will play the role of some_function in the step above.
3) Now we need to specify a_cell_array, i.e. the cell array that contains the first 38 cells of the target. That would be, simply dataCOMB{1,1}(1,1:38).
The solution:
This one-liner implements the plan:
Time = cellfun(#(x) x(1:1024,1), dataCOMB{1,1}(1,1:38), 'UniformOutput', false);
Then you can access your data as in this example:
this_time = Time{3};
Your error is with Time(t). That's not how you create a new variable in matlab. To do exactly what you want (ie, create variables names Time1, Time2, etc...you'll need to use the eval function:
for aa = 1:38
eval(['Time' num2str(aa) '= dataCOMB{1,1}{1,aa}(1:1024,1);']);
end
Many people do not like recommending the eval function. Others wouldn't recommend moving all of your data out of a data structure and into their own independently-named variables. So, to address these two criticisms, a better alternative might be to pull your data out of your complicated data structure and to put it into a simpler array:
Time_Array = zeros(1024,38);
for aa = 1:38
Time_Array(:,aa) = dataCOMB{1,1}{1,aa}(1:1024,1);
end
Or, if you don't like that because you really like the names Time1, Time2, etc, you could create them as fields to a data structure:
Time_Data = [];
for aa = 1:38
fieldname = ['Time' num2str(aa)];
Time_Data.(fieldname) = dataCOMB{1,1}{1,aa}(1:1024,1);
end
And, in response to a comment below by the original post, this method can be extended to further unpack the data:
Time_Data = [];
count = 0;
for z = 1:2;
for aa = 1:38
count = count+1;
fieldname = ['Time' num2str(count)];
Time_Data.(fieldname) = dataCOMB{1,z}{1,aa}(1:1024,1);
end
end

Read multiple values from array dynamically in MATLAB

I have an array of structures.
I'm trying to select several records from the array, that match some condition.
I know there's this option: (For example array A with field f1):
A([A.f1]==5)
Which would return all the records that have f1 = 5.
But I want to do it for several different fields, in a loop. I saved the fields names in a cell array, but I don't know how to do the same with a dynamic field name.
I know there's the 'getfield' function, but it only selects a field from a single structure.
Is there a way to do it?
Thanks!
To access dynamically a field of a structure:
% Create example structure
s.a = 1;
s.b = 2;
% Suppose you retrieve the fieldnames (or hardcode them fnames = {'a','b'})
fnames = fieldnames(s);
The you can retrieve e.g. the second one:
s.(fnames{2})
In a loop
for f = 1:numel(fnames)
s.(fnames{f})
end
In your case:
A([A.(fnames{ii})] == n)
This code will run through the first 5 records of your dynamical names
for i=1:5
eval(['A([A.' cell_array{i} ']==5)'])
end

Resources