contouring of 3 vectors
7 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
I'm trying to make a contour plot using three vectors. I want to contour chlorophyll as a function of depth and time. Each vector is a different length and so I keep getting an error when using interp2. I've also tried using griddata and I'm still getting errors, As well as TriScatterInterp. Can some help me de-bug one of the three ways.
x=dntime
x1=min(dntime)
y=depth_corrected
y1=min(depth_corrected)
%[X,Y]=meshgrid(x,y); %gives the depth/time mesh grid
%chloro
%Z=interp2(X,Y,chloro,x1,y1); %2d interpolation
F=TriScatteredInterp(dntime(:),depth_corrected(:),chloro(:));
dielcycle=F(dntime,depth_corrected);
contour(X,Y,Z)
% x=dntime
% y=depth_corrected
% xq=1:16
% yq=0:0.3500:max(depth_corrected) % depth range
% z=chloro
%vq=griddata(x,y,z,xq,yq) %not gonna work until you change time columns
2 comentarios
Cris LaPierre
el 30 de En. de 2021
It would also be helpful if you shared your X, Y and Z data. You can save them in a mat file and attach that to your post using the paperclip icon.
Respuestas (3)
Cris LaPierre
el 30 de En. de 2021
Editada: Cris LaPierre
el 30 de En. de 2021
I found myself bored, so played some more.
Challenges (not an exhaustive list)
- varying number of samples for a given time stamp
- no simple way to resample the data
- datetimes are not a valid input for some of the obvious functions, including contour
- data is not sorted
- inconsistent values of depth
- contour requires V to be a matrix, where rows correspond to depth and columns correspond to date.
After some playing around, I got something working. Key points are
- Obtain one value for each datetime and depth combination. I used groupsummary for this. A side benefit is that it returns a sorted table of increasing values (no duplicates). There are often multiple chloro values for a datetime-depth combination. In this case, I elected to use the median value, though there are many possible options (min, max, mean, custom function)
- I created a fixed depth increment using linspace. This is used to compute new chloro values at known depths for all dates.
- Since there is no obvious relationship day to day, I created a new matrix (rows=depth, columns=unique datetimes) and populated each column with the corresponding chloro values, obtained using interp1 with the known depths and chloro values, and interpolating to the fixed depth values.
- Contour does not allow an input of datetimes. I therefore convert the datetime to a numeric value representing elapsed time in days from the first date. This was arbitrary. I could have used seconds, minutes, hours, etc. The important thing is that it be a numeric value that retains the relative spacing between the dates.
% Load the data
opts = detectImportOptions("JCData.csv");
opts.VariableNames = ["dntime","depth","chloro"];
opts.Delimiter=["'",","];
opts.ConsecutiveDelimitersRule="join";
opts.LeadingDelimitersRule="ignore";
opts=setvartype(opts,"dntime","datetime");
opts=setvaropts(opts,"dntime","InputFormat","MM-dd-yyyy HH:mm:ss.SSSS");
data = readtable("JCData.csv",opts);
% Simplify the data to a single chloro value for each unqiue dntime and depth combination
dtTbl=groupsummary(data,["dntime","depth"],"median","chloro");
% Create uniformly sampled depth
dp=linspace(min(data.depth),max(data.depth));
% Extract unique datetime values
dt = unique(dtTbl.dntime)';
% Resample chloro values at each date using uniform depth vector and interp1
V=zeros(length(dp),length(dt));
for d = 1:length(dt)
ind = dtTbl.dntime==dt(d);
V(:,d) = interp1(dtTbl.depth(ind),dtTbl.median_chloro(ind),dp);
end
% Convert datetime to numeric representation
X = days(dt-dt(1));
% plot
contour(X,dp,V)
colorbar
0 comentarios
Star Strider
el 30 de En. de 2021
I was able to import these and get an actual datetime array out of the first column:
T1 = readtable('Data.csv');
T1.Var1 = cellfun(@(x)datetime(x,'InputFormat','''''MM-dd-yyyy HH:mm:ss.SSSS''''', 'Format','MM-dd-yyyy HH:mm:ss.SSSS'),T1.Var1);
[Ut,ia,ix] = unique(T1.Var1,'stable');
and an overview of the file:
Segments = diff(ia);
GS = groupsummary(T1,'Var1');
producing:
GS =
16×2 table
Var1 GroupCount
________________________ __________
08-16-2016 02:01:01.0000 1170
08-16-2016 03:56:28.0000 497
08-16-2016 05:56:36.0000 374
08-16-2016 07:57:30.0000 491
08-16-2016 10:02:23.0000 532
08-16-2016 11:59:36.0000 325
08-16-2016 11:59:37.0000 412
08-17-2016 01:56:15.0000 763
08-17-2016 02:03:10.0000 335
08-17-2016 03:59:40.0000 684
08-17-2016 04:00:04.0000 452
08-17-2016 04:53:44.0000 358
08-17-2016 05:58:19.0000 324
08-17-2016 08:00:14.0000 380
08-17-2016 09:59:44.0000 326
08-17-2016 10:56:04.0000 347
The problem is that since there are unequal numbers of each time, using reshape or griddata or any other function to create uniform arrays that contour would be able to use is simply not possible as the data currently exists.
This works for ‘TimeVector’:
TimeVector = linspace(min(T1.Var1), max(T1.Var1), 2000);
however this:
Cols23 = interp1(T1.Var1, T1{:,2:3}, TimeVector(:));
throws the expected error:
Sample points must be unique and sorted in ascending order.
I have no idea what to suggest.
2 comentarios
Cris LaPierre
el 30 de En. de 2021
Your data is not organized well enough to make conversion to a contour plot simple. Here is what I see when I load and plot the data.
opts = detectImportOptions("JCData.csv");
opts.VariableNames = ["dntime","depth","chloro"];
opts.Delimiter=["'",","];
opts.ConsecutiveDelimitersRule="join";
opts.LeadingDelimitersRule="ignore";
opts=setvartype(opts,"dntime","datetime");
opts=setvaropts(opts,"dntime","InputFormat","MM-dd-yyyy HH:mm:ss.SSSS");
data = readtable("JCData.csv",opts)
scatter3(data.dntime,data.depth,data.chloro)
Star Strider
el 30 de En. de 2021
I couldn’t make the delimiters work using character arrays, the reason I went with cellfun. Using string representations in the detectImportOptions customisation is definitely the only usable approach here. I’ll keep that in mind.
I agree that the data are not organised in a way that makes contour an option.
Jacqueline Chrabot
el 30 de En. de 2021
4 comentarios
Cris LaPierre
el 31 de En. de 2021
It may help to think of it this way. A contour plot is a way to visualize a matrix of values. The rows of that matrix correspond to your y values, and the columns correspond to x values. All values in the first column must correspond to the same x value, and all values in the first row must correspond to the max y value.The x and y values must be in the same order as you want the to appear.
Also, in order to create the plot every x-y combination must have a value assigned in this matrix.
Basically, arrange your data the same way as if you were going to create a heatmap, a surface, or even an image.
Walter Roberson
el 31 de En. de 2021
Alternately, use griddedInterpolant or scatteredInterpolant to create an interpolated grid of output, and contour that. I seem to recall someone contributed a File Exchange contribution for that purpose.
However, the scatter plot that Cris posted on https://www.mathworks.com/matlabcentral/answers/730953-contouring-of-3-vectors?s_tid=srchtitle#comment_1296278 implies to me that you do not have enough continuity of data to be doing a contour plot.
Ver también
Categorías
Más información sobre Contour Plots en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!