How do I organize this data into structures in MATLAB? - arrays

Say for n=5, the following code gives me a plot for n randomly generated nodes. These nodes are not structures (just plotted points), but I want to assign every node a message just as I did for sink and source and keep track of the nodes identity and location.
For example, if node 4 has (x,y) coordinates (.3452 , .5463), I want to assign node 4 a msg and temp_value as well. How can I do this?
Code:
n = input('No. of Nodes:');
sink = [0 0];
source = [1 1];
node = rand(n,2)
x = node(:,1);
y = node(:,2);
x1 = sink(:,1);
y1 = sink(:,1);
x2 = source(:,1);
y2 = source(:,1);
plot(x,y,'o')
hold on
plot(x1,y1,'r*')
hold on
plot(x2,y2,'r*')
hold on
sink = struct;
sink.msg = 'temp';
sink.temp_value = '30'
source = struct;
source.msg = 'temp';
source.temp_value = '30'

I would suggest creating an array of structures that stores all of the data associated with each "node". You can create all of the data for your nodes with one call to STRUCT in the following way:
N = 5; %# Number of nodes
coords = num2cell(rand(N,2)); %# Cell array of random x and y coordinates
nodes = struct('x',coords(:,1),... %# Assign x coordinates
'y',coords(:,2),... %# Assign y coordinates
'message','temp',... %# Assign default message
'value',30); %# Assign default value
The variable nodes is an N-by-1 structure array with fields x, y, message, and value. You can access and modify the data using the usual array and field indexing:
>> nodes(1) %# Contents of node 1
ans =
x: 0.4387
y: 0.4898
message: 'temp'
value: 30
>> nodes(1).message %# Message for node 1
ans =
temp
>> nodes(1).message = 'hello world!'; %# Change message for node 1
You can then plot the nodes in the following way:
plot([nodes.x],[nodes.y],'r*'); %# Plot all the nodes in red
index = randi(N,[1 2]); %# Pick two nodes at random
hold on;
plot([nodes(index).x],[nodes(index).y],'b*'); %# Plot 2 random nodes in blue

Related

How to select corresponding value in two data sets using matlab?

I have a two datasets (x,y) in in table:
x = [4.14;5.07;3.61;4.07;3.68;4.13;3.95;3.88;5.41;6.14]
y = [69.78;173.07;19.28;32.88;15.87;53.73;41.69;35.14;228.08;267.11];
tb = table(x,y)
edges = linspace(30, 0, 61);
Based on this I have written following program
for k = 1:length(x)
New(k) = find(x(k)>edges,1,'last');
end
I want to see datasets y which satisfying condition of of above x values.

Modify struct array and return struct array

I have a struct array: a 1x10 struct array with fields: N, t, q, r, T, each of which is a vector of type double.
The 10 array entries each represent the outcome of a testing condition in an experiment. I would like to be able to make a function that takes two indices, index1 and index2, and modifies the constituent N, t, q, r vectors (T is a single number) so that they become length index1:index2. Something like
function sa = modifier(struct_array, index1, index2)
sa = structfun(#(x) x(index1:index2), struct_array, 'UniformOutput', false)
stuff
end
Now, where stuff is, I've tried using structfun and cellfun, see here except that those return a struct and a cell array, respectively, whereas I need to return a struct array.
The purpose of this is to be able to get certain sections of the experimental results, e.g. maybe the first five entries in each vector inside each cell correspond to the initial cycles of the experiment.
Please let me know if this is possible, and how I might go about it!
You can try this:
From this question's answer, I figured out how to loop through struct fields. I modified the code to address your question by extracting a subsample from each field that goes through the for loop and then copy the desired subset of that data into a new struct array with identically named fields.
% Define indexes for extraction
fieldsToTrim = {'a' 'b'};
idx = 2:3; % Create index vector for extracting selected data range
% Define test struct to be read
teststruct.a = [1 2 3];
teststruct.b = [4 5 6];
teststruct.c = [7 8 9];
% Get names of struct fields
fields = fieldnames(teststruct);
% Loop through each field and extract the subset
for i = 1:numel(fields)
if max(strcmp(fields{i},fieldsToTrim)) > 0
% If current matches one of the fields selected for extraction
% extract subset
teststructResults.(fields{i}) = teststruct.(fields{i})(idx);
else
% Else, copy all contents on field to resulting struct
teststructResults.(fields{i}) = teststruct.(fields{i});
end
end
Finally, to turn this into a function, you can modify the above code to this:
function teststructResults = extractSubsetFromStruct(teststruct,fieldsToTrim,idx1, idx2)
% idx1 and idx2 are the start and end indicies of the desired range
% fieldsToTrim is a string array of the field names you want
% included in the trimming, all other fields will be fully copied
% teststruct is your input structure which you are extracting the
% subset from
% teststructResults is the output containing identically named
% struct fields to the input, but only containing data from the selected range
idx = idx1:idx2; % Create index vector for extracting selected data range
% Get names of struct fields
fields = fieldnames(teststruct);
% Loop through each field and extract the subset
for i = 1:numel(fields)
if max(strcmp(fields{i},fieldsToTrim)) > 0
% If current matches one of the fields selected for extraction
% extract subset
temp = teststruct.(fields{i});
teststructResults.(fields{i}) = temp(idx);
else
% Else, copy all contents on field to resulting struct
teststructResults.(fields{i}) = teststruct.(fields{i});
end
end
end
I successfully ran the function like this:
teststruct =
a: [1 2 3]
b: [4 5 6]
c: [7 8 9]
>> extractSubsetFromStruct(teststruct,{'a' 'b'},2,3)
ans =
a: [2 3]
b: [5 6]
c: [7 8 9]

Data from array struct in corresponding shape

Say, we have an array of structs
data = struct('position',[]);
data(1,1).position = 11;
data(1,2).position = 12;
data(2,1).position = 21;
data(2,2).position = 22;
I learned that to get the entries from a field from all structs in the array, we can use
>> [data.position]
ans =
11 21 12 22
But this gives the data in a row. How can we get it in the original shape of the array, without looping the array in MCode?
Desired output:
position =
11 12
21 22
Use reshape. This will restructure an input vector / matrix into another vector / matrix of a desired shape. Specifically, you can specify the dimensions of data into reshape as well as the row vector produced by [data.position] and it'll reshape the vector with the right dimensions for you.
data = struct('position',[]);
data(1,1).position = 11;
data(1,2).position = 12;
data(2,1).position = 21;
data(2,2).position = 22;
position = reshape([data.position], size(data))
position =
11 12
21 22
Note that the elements are shaped in column-major format so the values are stacked column-wise. As you can see, the first two elements become the first column of the output matrix, while the last two elements become the second column of the output matrix.
If you are working with empty entries, you can use struct2cell to convert the struct data into cell array that enables us to store empty entries as empty cells -
data_cell = permute(struct2cell(data),[2 3 1])
out = data_cell(:,:,strcmp(fieldnames(data),'position'))
So, if you have something like this with the (2,2) missing -
data = struct('position',[]);
data(1,1).position = 11;
data(1,2).position = 12;
data(2,1).position = 21;
You would have -
out =
[11] [12]
[21] []
Based on #CitizenInsane's nice observation and which might be very close to #rayryeng's answer, but one that deals with cell arrays instead of numeric arrays, would be this -
out = reshape({data.position}, size(data))

MatLab find cells with specific values in two cell arrays

I want to find cells, which are at the same position in two different cell arrays and which have specific values.
The two cell arrays have the following structure:
cell array C1= cell(20,1). In each cell there is another cell cell(8129,8) holding double values in the range of [0,1].
Cell array C2= cell(20,1). In each cell there is another cell cell(8192,8) also holding double values in the range of [0,1].
I know want to find those cells, which (1) have a specific value that I determine (e.g. C1_value = 0.8 and C2_value = 0.85) and (2) are at the same position in the respective sub cell (!) array (e.g. C1{2}(736) == 0.8 and C2(19)(736) == 0.85). NOTE: The same position only refers to the subcell arrays (cell(8192,8)) not the "main" cell arrays C1(:) and C2(:)
Thanks in advance!
See if this approach works for you -
sz = cell2mat(cellfun(#size,C1(1),'uni',0))
row1 = sz(1);
col1 = sz(2);
t1 = reshape(horzcat(C1{:}),row1,col1,[])
t2 = reshape(horzcat(C2{:}),row1,col1,[])
b1 = t1==C1_value
b2 = t2==C2_value
tt1 = reshape(b1,row1*col1,[])' %//'
tt2 = reshape(b2,row1*col1,[])' %//'
tt22 = permute(tt2,[3 2 1])
tt3 = bsxfun(#and,tt1,tt22)
[C1_cellnum,subcellnum,C2_cellnum] = ind2sub(size(tt3),find(tt3)) %// outputs
Thus, with your sample data, you must have -
C1_cellnum as 2, C2_cellnum as 19 and subcellnum as 736.

How to read specific fields from multiple structure arrays in MATLAB?

I have a very large dataset arranged into multiple structure arrays in MATLAB. The structures look something like this:
Flight1=
.testpoint = 1
.Mach = 0.8
.Speed = 300
.Cieling = 35000
.Data = [A] % A is an MxN matrix
Similarly there are multiple test points for multiple flights. Is there a way to retrieve the Data of only specified test points? For example I want to look at the Data of ALL the test points whose .Mach = 0.8 or where .testpoint = 2?
I hope I have made it clear enough.
Assuming you have a struct array Flight where Flight( k ) is a struct with the fields you described, then:
sel = [ Flight(:).Mach ] == 0.8; % select all flights with Mach == 0.8
poitEightMach = Flight( sel ); % selecting them into a separate struct array
sel = [Flight(:).testpoint] == 2;
testPoint2 = Flight( sel ); % select all flights with testpoint == 2

Resources