contouring of 3 vectors

11 vues (au cours des 30 derniers jours)
Jacqueline Chrabot
Jacqueline Chrabot le 30 Jan 2021
Commenté : Walter Roberson le 31 Jan 2021
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 commentaires
Cris LaPierre
Cris LaPierre le 30 Jan 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.
Jacqueline Chrabot
Jacqueline Chrabot le 30 Jan 2021
Attached is the data. I indexed them so they are there own arrays. From left to right is dntime (date and time) in the same column, then the depth, and then, the chloro measurement taken at that depth and time. I want to contour the chloro with depth being the y and date/time being on the x axis.

Connectez-vous pour commenter.

Réponses (3)

Star Strider
Star Strider le 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 commentaires
Cris LaPierre
Cris LaPierre le 30 Jan 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)
data = 7770x3 table
dntime depth chloro ________________________ _____ ______ 08-16-2016 11:59:36.0000 0.001 49.1 08-16-2016 11:59:36.0000 0.001 48.5 08-16-2016 11:59:36.0000 0.001 48.2 08-16-2016 11:59:36.0000 0.001 47.6 08-16-2016 11:59:36.0000 0.001 48.1 08-16-2016 11:59:36.0000 0.001 47.7 08-16-2016 11:59:36.0000 0.001 47.5 08-16-2016 11:59:36.0000 0.001 47 08-16-2016 11:59:36.0000 0.001 46.7 08-16-2016 11:59:36.0000 0.001 46.7 08-16-2016 11:59:36.0000 0.001 46.5 08-16-2016 11:59:36.0000 0.001 46.5 08-16-2016 11:59:36.0000 0.001 46.4 08-16-2016 11:59:36.0000 0.001 46.5 08-16-2016 11:59:36.0000 0.001 46.3 08-16-2016 11:59:36.0000 0.001 46.3
scatter3(data.dntime,data.depth,data.chloro)
Star Strider
Star Strider le 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.

Connectez-vous pour commenter.


Cris LaPierre
Cris LaPierre le 30 Jan 2021
Modifié(e) : Cris LaPierre le 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
  1. 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)
  2. I created a fixed depth increment using linspace. This is used to compute new chloro values at known depths for all dates.
  3. 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.
  4. 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

Jacqueline Chrabot
Jacqueline Chrabot le 30 Jan 2021
So I guess maybe this will help. I put those three arrays in a new table but maybe I should have attached the original table. There are essentially 16 tables of data I combined together using Vertcat and changed the date/time of each one of those 16 tables to the first date that was listed(so there will be 16 different dates and times) I thought this would help contour. I just wanted to contour the chlorophyll (I guess this would be z), in respect to yreverse the depth (0:max(depth_corrected)) and x the date & time. My goal is to see what the chlorophyll levels are doing in the water column. Per the original table, the chlorophyll measurements are Var11, and depth_corrected is Var7. Obviously date and time are the 1st and 2nd column. I'm kind of getting confused by all the posts as to what I need to do.
  4 commentaires
Cris LaPierre
Cris LaPierre le 31 Jan 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
Walter Roberson le 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.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Contour Plots dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by