contouring of 3 vectors
7 views (last 30 days)
Show older comments
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 Comments
Answers (3)
Star Strider
on 30 Jan 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 Comments
Star Strider
on 30 Jan 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.
Cris LaPierre
on 30 Jan 2021
Edited: Cris LaPierre
on 30 Jan 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 Comments
Jacqueline Chrabot
on 30 Jan 2021
4 Comments
Walter Roberson
on 31 Jan 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.
See Also
Categories
Find more on Contour Plots in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!