I'd like to create a quasi boxplot graph as shown on pages 15/16 of the attached report.
comisef.eu/files/wps031.pdf
Ideally I only want to show the median, the maximum and minimum values as in the report.
I would also like to have similar spacing to that shown in the report.
Currently I have two matrices with the all the necessary values stored in them but have no idea how to do this in matlab.
The boxplot function gives too much data (outliers etc) which makes the resulting graph look confused especially when I try to plot 200 on one page as in the original report.
Is there another function that can so the same thing as in the report in matlab?
Baz
OK here is some test data each row represents 10 sets of estimations of a data set, and each column represents the test number for a given observation.
As boxplot works on the columns of the input matrix you will need to transpose the matrix.
Is it possible to turn outliers and the inter-quartile ranges off? Ideally I just want to see the maximum, minimum and median values?
You can repeat the data below to get up to 200. Or I can send more data if necessary.
0.00160329732202511 0.000859407819412016 0.000859407819411159 0.0659939338995606 0.000859407819416322 0.000859407819416519 2.56395024851142e-15 2.05410662537078e-14 0.000859407819416209
1.67023155116586e-06 8.88178419700125e-16 1.67023155115637e-06 0.000730536218639616 1.67023155105582e-06 3.28746017489609e-15 4.41416632660789e-15 1.67023155094400e-06 1.67023155097567e-06
1.42410590843629e-06 1.42410590840224e-06 1.76149166727218e-15 5.97790925044131e-15 1.42410590843863e-06 2.87802701599909e-15 9.31529385335274e-16 9.17306727455842e-16 0.000820358763518906
8.26849110292527e-16 3.23505095414772e-15 4.38139485761850e-07 4.38139485938112e-07 4.38139485981887e-07 0.000884647755317917 3.72611754134110e-15 4.38139485974329e-07 4.38139485923219e-07
0.000160661751819407 0.000870787937135265 0.000870787937136209 1.16934122581182e-15 9.02860049358913e-16 1.18053134896556e-15 1.40433338743068e-15 0.000870787937135929 1.13510916297112e-15
1.16934122581182e-15 3.80292342262841e-05 3.80292342263200e-05 0.00284904319356532 1.74649997619656e-15 3.80292342264024e-05 0.00284904319356537 1.01267920724547e-15 0.00284904319356540
0.100091800399985 0.100091773169254 0.100091803903140 0.000770464183529358 0.100091812455930 3.49996706323281e-05 3.49996706323553e-05 1.05090687851466e-15 0.100091846333800
0.00100555294602561 0.00100555294601056 0.105365907420183 0.000121078082591672 9.02860049358913e-16 0.000121078082591805 4.49679158258033e-15 7.77684615168284e-16 0.000121078082591693
0.122539456858702 0.000363547764643498 0.000363547764643509 0.122516928568610 0.0101487499394213 0.122408366511784 0.000363547764643519 1.13510916297112e-15 0.122521393586646
0.000460749357561036 0.000460749357560646 3.27600489447913e-13 1.18053134896556e-15 0.000460749357561239 1.54689304063675e-15 0.000460749357560827 0.000460749357561205 1.16934122581182e-15
Instead of using boxplot, I suggest just drawing lines from the min to the max and making a mark at the median. Boxplot draws boxes from the 25 to 75 percentile, which doesn't sound like what you want. Something like this:
% fake data
nPoints = 100;
data = 10*rand(10, nPoints);
% find statistics
minData = min(data, [], 1);
maxData = max(data, [], 1);
medData = median(data);
% x coordinates of each line. Change this to change the spacing.
x = 1:nPoints;
figure
hold on
%plot lines
line([x; x], [minData; maxData])
% plot cross at median
plot(x, medData, '+')
EDIT: To have horizontal lines and a second axis you can do something like this:
figure
h1 = subplot(1,2,1);
h2 = subplot(1,2,2);
% left subplot
axes(h1)
hold on
%plot lines
line([minData; maxData], [x; x])
% plot cross at median
plot(medData, x, '+')
% link the axes so they will have the same limits
linkaxes([h1,h2],'y')
% turn off ticks on y axis.
set(h2, 'YTick', [])
I think it's a question of playing with the settings. You can try:
boxplot(X, 'plotstyle', 'compact', 'colors', 'k', 'medianstyle', 'line', 'outliersize', 0);
Explanation:
'plotstyle', 'compact': makes the boxes filled and the lines undashed
'colors', 'k': color is black
'medianstyle', 'line': the median is marked by a line
'outliersize', 0: if outlier size is zero, you don't see them
Other you can try:
'orientation', 'vertical': this flips the orientation, depends on your data
'whisker', 10 (or higher): this sets the maximum whisker length as a function of the interquartile limits (if you crank it up, it will eventually default to max and min values), I wasn't sure if this is what you wanted. Right now, it goes to the 25th and 75th percentile values.
The spacing is going to depend on how much data you have. If you edit with some data, I can try it out for you.
Related
I produced a plot that contains 50 curves and each of them corresponds to a specific value of a parameter called "Jacobi constant", so I have 50 values of jacobi constant stored in array called jacobi_cst_L1:
3.000900891023230
3.000894276927840
3.000887643313580
3.000881028967010
3.000874419173230
3.000867791975870
3.000861196034850
3.000854592397690
3.000847948043080
3.000841330136040
3.000834723697250
3.000828099771820
3.000821489088600
3.000814922863360
3.000808265737810
3.000801695858850
3.000795067776960
3.000788475204760
3.000781845363950
3.000775192199620
3.000768609354090
3.000761928862980
3.000755335851910
3.000748750854930
3.000742084743060
3.000735532899990
3.000728906460450
3.000722309400740
3.000715644446600
3.000709016645110
3.000702431180730
3.000695791284050
3.000689196186970
3.000682547292110
3.000675958537960
3.000669315388860
3.000662738391370
3.000656116141060
3.000649560630930
3.000642857256680
3.000636330415510
3.000629657944820
3.000623060310100
3.000616425935580
3.000609870077710
3.000603171772120
3.000596554947660
3.000590018845460
3.000583342259840
3.000576748353570
I want to use a colormap to color my curves and then show in a lateral bar the legend that show the numerical values corresponding to each color of orbit.
By considering my example image, I would want to add the array of constants in the lateral bar and then to color each curve according the lateral bar.
% Family of 50 planar Lyapunov orbits around L1 in dimensionless unit
fig = figure;
for k1 = 1:(numel(files_L1_L2_Ly_prop)-2)
plot([Ly_orb_filt(1).prop(k1).orbits.x],[Ly_orb_filt(1).prop(k1).orbits.y],...
"Color",my_green*1.1); hold on %"Color",my_green*1.1
colorbar()
end
axis equal
% Plot L1 point
plot(Ly_orb_filt_sys_data(1).x,Ly_orb_filt_sys_data(1).y,'.',...
'color',[0,0,0],'MarkerFaceColor',my_green,'MarkerSize',10);
text(Ly_orb_filt_sys_data(1).x-0.00015,Ly_orb_filt_sys_data(1).y-0.0008,'L_{1}');
%Primary bodies plots
plot(AstroData.mu_SEM_sys -1,0,'.',...
'color',my_blue,'MarkerFaceColor',my_blue,'MarkerSize',20);
text(AstroData.mu_SEM_sys-1,0-0.001,'$Earth + Moon$','Interpreter',"latex");
grid on;
xlabel('$x$','interpreter','latex','fontsize',12);
ylabel('$y$','interpreter','latex','FontSize',12);
How can I color each line based on its Jacobi constant value?
You can use any colour map to produce a series of RGB-triplets for the plotting routines to read (Or create an m-by-3 matrix with elements between 0 and 1 yourself):
n = 10; % Plot 10 lines
x = 1:15;
colour_map = jet(n); % Get colours. parula, hsv, hot etc.
figure;
hold on
for ii = 1:n
% Plot each line individually
plot(x, x+ii, 'Color', colour_map(ii, :))
end
colorbar % Show the colour bar.
Which on R2007b produces:
Note that indexing into a colour map will produce linearly spaced colours, thus you'll need to either interpolate or calculate a lot to get the specific ones you need. Then you can (need to?) modify the resulting colour bar's labels by hand to reflect your input values. I'd simply use parula(50), treat its indices as linspace(jacobi(1), jacobi(end), 50) and then my_colour = interp1(linspace(jacobi(1), jacobi(end), 50), parula(50), jacobi).
So in your code, rather than using "Color",my_green*1.1 for each line, use "Color",my_colour(kl,:), where my_colour is whatever series of RGB triplets you have defined.
I want to set the limit for X axis in this plot from 0 to 325. When i am using xlim to set the limits (commented in the code). It doesn't work properly. When i use xlim, the entire structure of plot changes. Any help will be appreciated.
figure
imagesc(transpose(all_area_for_visual));
colormap("jet")
colorbar('Ticks',0:3,'TickLabels',{'Home ','Field','Bad house','Good house'})
xlabel('Time (min)')
tickLocs = round(linspace(1,length(final_plot_mat_missing_part(2:end,1)),8));
timeVector = final_plot_mat_missing_part(2:end,1);
timeForTicks = (timeVector(tickLocs))./60;
xticks(tickLocs);
xticklabels(timeForTicks);
%xlim([0 325]);
ylabel('Car identity')
yticks(1:length(Ucolumnnames_fpm))
yticklabels([Ucolumnnames_fpm(1,:)])
If I get you right, you want to plot only part of the data in all_area_for_visual, given by a condition on tickLocs. So you should first condition the data, and then plot it:
% generate the vector of x values:
tickLocs = round(linspace(1,length(final_plot_mat_missing_part(2:end,1)),8));
% create an index vector (of logicals) that marks the columns to plot from the data matix:
validX = tickLocs(tickLocs<=325);
% plot only the relevant part of the data:
imagesc(transpose(all_area_for_visual(:,validX)));
% generate the correct ticks for the data that was plotted:
timeVector = final_plot_mat_missing_part(2:end,1);
timeForTicks = (timeVector(tickLocs(validX)))./60;
xticks(tickLocs(validX));
% here you continue with setting the labels, colormap and so on...
imagesc puts the data in little rectangles centered around integers 1:width and 1:height by default. You can specify what the x and y locations of each data point by adding two vectors to the call:
imagesc(x,y,transpose(all_area_for_visual));
where x and y are vectors with the locations along the x and y axes you want to place the data.
Note that xlim and xticks don’t change the location of the data, only the region of the axis shown, and the location of tick marks along the axis. With xticklabels you can change what is shown at each tick mark, so you can use that to “fake” the data locations, but the xlim setting still applies to the actual locations, not to the labels assigned to the ticks.
I think it is easier to plot the data in the right locations to start with. Here is an example:
% Fake your data, I'm making a small matrix here for illustration purposes
all_area_for_visual = min(floor(cumsum(rand(20,5)/2)),3);
times = linspace(0,500,20); % These are the locations along the time axis for each matrix element
car_id_names = [4,5,8,15,18]; % These are the labels to put along the y-axis
car_ids = 1:numel(car_id_names); % These are the locations to use along the y-axis
% Replicate your plot
figure
imagesc(times,car_ids,transpose(all_area_for_visual));
% ^^^ ^^^ NOTE! specifying locations
colormap("jet")
colorbar('Ticks',0:3,'TickLabels',{'Home ','Field','Bad house','Good house'})
xlabel('Time (min)')
ylabel('Car identity')
set(gca,'YTick',car_ids,'YTickLabel',car_id_names) % Combine YTICK and YTICKLABEL calls
% Now you can specify your limit, in actual time units (min)
xlim([0 325]);
I am trying to adjust the scale of the x-axis so that the values are closer together, but I am not able to do so.
I need the output to be like this photo:
However, what I actually get is the photo below:
Here's the code I have written to reproduce this error:
x = [0.1 1 10 100 1000 10000];
y = [1.9904 19.8120 82.6122 93.0256 98.4086 99.4016];
figure;
bar(x,y);
ylabel('Y values');
xlabel('X values');
set(gca,'XTick', [0.1 1 10 100 1000 10000])
How can I adjust the x-axis so that it looks like the first photo?
Because your data has such huge dynamic range, and because of the linear behaviour of the x axis, your graph is naturally going to appear like that. One compromise that I can suggest is that you transform your x data so that it gets mapped to a smaller scale, then remap your x data so that it falls onto a small exponential scale. After, simply plot the data using this remapped scale, then rename the x ticks so that they have the same values as your x data. To do this, I would take the log10 of your data first, then apply an exponential to this data. In this way, you are scaling the x co-ordinates down to a smaller dynamic range. When you apply the exponential to this smaller range, the x co-ordinates will then spread out in a gradual way where higher values of x will certainly make the value go farther along the x-axis, but not too far away like you saw in your original plot.
As such, try something like this:
x = [0.1 1 10 100 1000 10000]; %// Define data
y = [1.9904 19.8120 82.6122 93.0256 98.4086 99.4016];
xplot = (1.25).^(log10(x)); %// Define modified x values
figure;
bar(xplot,y); %// Plot the bar graph on the modified scale
set(gca,'XTick', xplot); %// Define ticks only where the bars are located
set(gca,'XTickLabel', x); %// Rename these ticks to our actual x data
This is what I get:
Note that you'll have to play around with the base of the exponential, which is 1.25 in what I did, to suit your data. Obviously, the bigger the dynamic range of your x data, the smaller this exponent will have to be in order for your data to be closer to each other.
Edit from your comments
From your comments, you want the bars to be equidistant in between neighbouring bars. As such, you simply have to make the x axis linear in a small range, from... say... 1 to the total number of x values. You'd then apply the same logic where we rename the ticks on the x axis so that they are from the true x values instead. As such, you only have to change one line, which is xplot. The other lines should stay the same. Therefore:
x = [0.1 1 10 100 1000 10000]; %// Define data
y = [1.9904 19.8120 82.6122 93.0256 98.4086 99.4016];
xplot = 1:numel(x); %// Define modified x values
figure;
bar(xplot,y); %// Plot the bar graph on the modified scale
set(gca,'XTick', xplot); %// Define ticks only where the bars are located
set(gca,'XTickLabel', x); %// Rename these ticks to our actual x data
This is what I get:
So I'm still getting used to Matlab and am having a bit of trouble with plotting. I have a cell which contains a list of points in each row. I want to plot each row of points in a different colour on the same graph so I can compare them. The catch is that I need to make this work for an unknown number of points and rows (ie the number of points and rows can change each time I run the program).
So for example, I might have my cell array A:
A = {[0,0], [1,2], [3,4]; [0,0] [5,6], [9,2]}
and I want to plot the points in row 1 against their index (so a 3D graph) and then have the points in row 2 on the same graph in a different colour. The rows will always be the same length. (Each row will always have the same number of points). I've tried a few different for loops but just can't seem to get this right.
Any help in sending me in the right direction would be greatly appreciated!
The fact that the number of points and rows can change with each iteration should not pose much of a problem. I would suggest using the size function before your plot loops (size(A,1) and size(A,2)) to get the dimensions of the matrix.
Once you have the size of the matrix, loop through the dimensions and plot the lines on the same plot using holdon, and then finally just make the line color a function of the dimensions as you loop through so that you always have a different line color
You could just convert it to a matrix and plot it directly:
% Some dummy data - format a little different from your example
% to allow for different numbers of elements per row
A = {[0,0, 1,2, 3,4]; [0,0, 5,6]};
% Figure out how many columns we need in total
maxLen = max(cellfun(#length, A));
% Preallocate
Amat = NaN(size(A, 1), maxLen);
% Copy data
for n = 1:size(A, 1)
curA = A{n};
Amat(n, 1:length(curA)) = curA;
end
% Generate 1:N vector repeated the correct number of times (rows)
x = repmat(1:size(Amat, 2), size(Amat, 1), 1);
plot(x, Amat)
Edit: You mentioned a 3D graph at some point in your post. The above won't plot a 3D graph, so here's something that will:
% Generate Amat as above
% Then:
[X, Y] = meshgrid(1:size(Amat, 1), 1:size(Amat, 2));
surf(X, Y, Amat.'); % OR: plot3(X, Y, Amat.');
I'm not sure this is exactly what you want, but your question is slightly unclear on exactly what kind of graph you want out of this. If you just want coloured lines on your plot, you can use plot3 instead of surf, but IMHO surf will probably give you a clearer plot for this kind of data.
I am currently a begineer, and i am using matlab to do a data analysis. I have a a text file with data at the first row is formatted as follow:
time;wave height 1;wave height 2;.......
I have column until wave height 19 and rows total 4000 rows.
Data in the first column is time in second. From 2nd column onwards, it is wave height elevation which is in meter. At the moment I like to ask matlab to plot a 3d graph with time on the x axis, wave elevation on the y axis, and wave elevation that correspond to wave height number from 1 to 19, i.e. data in column 2 row 10 has a let say 8m which is correspond to wave height 1 and time at the column 1 row 10.
I have try the following:
clear;
filename='abc.daf';
path='C:\D';
a=dlmread([path '\' filename],' ', 2, 1);
[nrows,ncols]=size(a);
t=a(1:nrows,1);%define t from text file
for i=(1:20),
j=(2:21);
end
wi=a(:,j);
for k=(2:4000),
l=k;
end
r=a(l,:);
But everytime i use try to plot them, the for loop wi works fine, but for r=a(l,:);, the plot only either give me the last time data only but i want all data in the file to be plot.
Is there a way i can do that. I am sorry as it is a bit confusing but i will be very thankful if anyone can help me out.
Thank you!!!!!!!!!!
Once you load your data as you do in your code above your variable a should be a 4000-by-20 array. You could then create a 3-D plot in a couple of different ways. You could create a 3-D line plot using the function PLOT3, plotting one line for each column of wave elevation data:
t = a(:,1); %# Your time vector
for i = 2:20 %# Loop over remaining columns
plot3(t,(i-1).*ones(4000,1),a(:,i)); %# Plot one column
hold on; %# Continue plotting to the same axes
end
xlabel('Time'); %# Time on the x-axis
ylabel('Wave number'); %# Wave number (1-19) on y-axis
zlabel('Wave elevation'); %# Elevation on z-axis
Another way to plot your data in 3-D is to make a mesh or surface plot, using the functions MESH or SURF, respectively. Here's an example:
h = surf(a(:,1),1:19,a(:,2:20)'); %'# Plot a colored surface
set(h,'EdgeColor','none'); %# Turn off edge coloring (easier to see surface)
xlabel('Time'); %# Time on the x-axis
ylabel('Wave number'); %# Wave number (1-19) on y-axis
zlabel('Wave elevation'); %# Elevation on z-axis
I don't quite understand what your function does, for example, I do not see any plot command.
Here's how I'd try to make a 3D plot according to your specs:
%# Create some data - time from 0 to 2pi, ten sets of data with frequency 1 through 10.
%# You would just load A instead (I use uppercase just so I know that A is a 2D array,
%# rather than a vector)
x = linspace(0,2*pi,100)';%#' linspace makes equally spaced points
w = 1:10;
[xx,ww]=ndgrid(x,w); %# prepare data for easy calculation of matrix A
y = ww.*sin(xx.*ww);
A = [x,y]; %# A is [time,data]
%# find size of A
[nRows,nCols] = size(A);
%# create a figure, loop through the columns 2:end of A to plot
colors = hsv(10);
figure,
hold on,
for i=1:nCols-1,
%# plot time vs waveIdx vs wave height
plot3(A(:,1),i*ones(nRows,1),A(:,1+i),'Color',colors(i,:)),
end
%# set a reasonable 3D view
view(45,60)
%# for clarity, label axes
xlabel('time')
ylabel('wave index')
zlabel('wave height')
Or, you could try gnuplot. Fast, free and relatively easy to use. I use it to generate heat maps for datasets in the millions of rows.