For loop using Struct data with multiple values per timepoint

조회 수: 3 (최근 30일)
Ryan Hecksel
Ryan Hecksel 2022년 12월 2일
답변: Seth Furman 2022년 12월 7일
Hello,
I am new to matlab so bear with me:
I currently have a 1x1 struct called "XY11" that contains 3 fields "DNA", "EGFRN" and "EGFRC" which are each 29890x1 structs with multiple fields. Particularly, I want to extract the "Integrated Intensity" and "Timepoint" fields, so I can plot the intensity of my objects over time.
Problem is, there are about 200-300 intensities per timepoint. There are 145 timepoints. I've written code to identify and average the intensities for a given timepoint, but I don't know how to structure the For loop so that each of my 145 timepoints is seperated into their own structure. See the code below.
% Identify all timepoints in the DNA struct
time = [XY11.DNA.Timepoint];
% Identify all intensities in the DNA struct
intensity = [XY11.DNA.IntegratedIntensity];
% Set time == 1 to evaluate intensities found in the first timepoint out of 145
timepoint1 = time == 1;
% Create a structure containing all of these timepoints
% Essentially a Struct containing only the number '1', but it helps me keep my timepoints organized
str.time = time(timepoint1);
% Create a structure containing all of the intensities found at timepoint 1
str.intensity = intensity(timepoint1);
% Find the mean of time (1, or whatever time ==) and intensity
means = structfun(@mean, str, 'uniform', 0);
% Find the STD of time (0, because it is unchaning) and intensity
stds = structfun(@std, str, 'uniform', 0);
The output of this code, Struct "str" is attached.
I don't know how to do the "For j = 1:num" thing, because I don't know how to define num. In my XY11.DNA structure there are hundreds of intensities per timepoint, so I'm not sure how to get matlab to know I need it to loop through all 145 timepoints. Maybe I'm just having "writer's block".
Your assistance is greatly appreciated.
  댓글 수: 2
Jiri Hajek
Jiri Hajek 2022년 12월 2일
Hi, maybe you are not aware of the size function, to give you the "num"?
Ryan Hecksel
Ryan Hecksel 2022년 12월 2일
Hi Jiri, thanks for your response.
size(XY11.DNA.Timepoint0; returns 29890 colums each filled with '1'
size(str.time); returns 1 and 214, the number of intensities found in timepoint 1
time = [XY11.DNA.Timepoint];
intensity = [XY11.DNA.IntegratedIntensity];
for i=1:145
timepoint(i) = time == (i)
str.time = time(timepoint(i))
str.intensity = intensity(timepoint(i))
end
I need i to loop through 145 times, where time == i, but when I run this, I get "Unable to perform assignment because the indices on the left side are not compatible with the size of the right side."

댓글을 달려면 로그인하십시오.

채택된 답변

Stephen23
Stephen23 2022년 12월 3일
편집: Stephen23 2022년 12월 3일
This would be a thousand times easier to answer if you had uploaded some sample data in the original format.
Instead of actually helping you, I will have to first try and replicate your data structure. Because your explanation is incomplete, I will assume that all 'IntegratedIntensity' and 'Timepoint' data are scalar numeric, and even then my structure might be wrong: much better would be, if you uploaded a sample data structure (which does not have to be all of it, just enough to work with).
As an aside, that data structure would be much much better as 1x1 structures containing 29890x1 numeric fields, rather than 29890x1 structures containing 1x1 fields.
% Fake data structure:
N = 29890;
S.DNA = cell2struct(num2cell([123*rand(N,1),randi(145,N,1)]),{'IntegratedIntensity','Timepoint'},2);
S.ABC = cell2struct(num2cell([123*rand(N,1),randi(145,N,1)]),{'IntegratedIntensity','Timepoint'},2);
S.XYZ = cell2struct(num2cell([123*rand(N,1),randi(145,N,1)]),{'IntegratedIntensity','Timepoint'},2)
S = struct with fields:
DNA: [29890×1 struct] ABC: [29890×1 struct] XYZ: [29890×1 struct]
S.DNA
ans = 29890×1 struct array with fields:
IntegratedIntensity Timepoint
% Get unique times:
iin = [S.DNA.IntegratedIntensity];
tpt = [S.DNA.Timepoint];
[uni,~,idx] = unique(tpt);
% Means and standard deviations:
allmeans = accumarray(idx,iin(:),[],@mean); % or GROUPSUMMARY
allstdev = accumarray(idx,iin(:),[],@std); % or GROUPSUMMARY
%
plot(uni,allmeans, uni,allstdev)
legend({'Means','Standard Deviations'})

추가 답변 (2개)

Eric Delgado
Eric Delgado 2022년 12월 3일
I don't know if I understand your issue, but...
uniqueTimePoints = unique(XY11.DNA.Timepoint);
for ii = 1:numel(uniqueTimePoints)
idx = XY11.DNA.Timepoint == uniqueTimePoints(ii);
str(ii).time = uniqueTimePoints(ii);
str(ii).intensity = intensity(idx);
str(ii).mean = mean(str(ii).intensity);
str(ii).std = std(str(ii).intensity);
end
  댓글 수: 4
Ryan Hecksel
Ryan Hecksel 2022년 12월 3일
Hi Eric,
Thanks for the help. XY11 is a struct containing 3 structs, DNA, EGFRN, and EGFRC. Each of those is a 29890x1 struct.
Stephen23
Stephen23 2022년 12월 3일
"but for some reason, uniqueTimePoints = unique(XY11.DNA.Timepoint) return an error: "
It returns an error because Eric Delgado's code provides 29890 inputs to UNIQUE, and is equivalent to doing this:
unique(XY11.DNA(1).Timepoint, XY11.DNA(2).Timepoint, .. , XY11.DNA(29890).Timepoint)
Clearly that is not going to do anything useful for you. As the original question shows, using concatenation is one way to handle that comma-separated list correctly. See also:

댓글을 달려면 로그인하십시오.


Seth Furman
Seth Furman 2022년 12월 7일
Alternatively, you can convert your struct into a table using struct2table.
load str.mat
t = struct2table(str)
t = 1×2 table
time intensity ____________ ____________ 1×214 double 1×214 double
varNames = t.Properties.VariableNames;
t = varfun(@transpose,t);
t.Properties.VariableNames = varNames
t = 214×2 table
time intensity ____ __________ 1 3.2815e+06 1 2.5435e+06 1 3.6094e+06 1 2.8818e+06 1 3.3884e+06 1 5.8135e+06 1 4.6849e+06 1 5.1159e+06 1 4.0684e+06 1 3.6248e+06 1 2.3786e+06 1 2.7508e+06 1 2.784e+06 1 3.5541e+06 1 2.5174e+06 1 2.9252e+06
Then, you can use groupsummary to get the mean for each unique time.
tSummary = groupsummary(t,"time",["mean","std"])
tSummary = 1×4 table
time GroupCount mean_intensity std_intensity ____ __________ ______________ _____________ 1 214 6.7187e+06 3.0742e+06
stackedplot(tSummary,["mean_intensity","std_intensity"],Marker="*",MarkerEdgeColor="red",XVariable="time")
Aside: You can also convert the time variable to the appropriate duration or datetime if desired.
tSummary.time = seconds(tSummary.time)
tSummary = 1×4 table
time GroupCount mean_intensity std_intensity _____ __________ ______________ _____________ 1 sec 214 6.7187e+06 3.0742e+06
tSummary = table2timetable(tSummary)
tSummary = 1×3 timetable
time GroupCount mean_intensity std_intensity _____ __________ ______________ _____________ 1 sec 214 6.7187e+06 3.0742e+06
stackedplot(tSummary,["mean_intensity","std_intensity"],Marker="*",MarkerEdgeColor="red")

카테고리

Help CenterFile Exchange에서 Matrices and Arrays에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by