Exchange subplots in figure - matlab

I create a figure containing 4 subplots like:
y = [2 2 3; 2 5 6; 2 8 9; 2 11 12];
fig = figure
for i = 1 : 4
h(i) = subplot(1,4,i)
bar(y)
end
Now I would like to exchange the order of the subplots. For example the first subplot should go in the last column (4th) and the 2nd subplot should exchange with the 3rd.
Is it doable without generating again the figure?

Perhaps you could change their 'position' of the axes h. For instance:
% get position
pos = get(h,'position');
% change position, 1st <-> 4th, 2nd <->3rd.
set(h(1),'position',pos{4});
set(h(4),'position',pos{1});
set(h(2),'position',pos{3});
set(h(3),'position',pos{2});

There is a possibility which kind of regenerates the figure. You can go to the plot tools, right click the figure and select "Show code". This will open a new file with a function that recreates the figure. There you can change your subplot-position and call the function in order to obtain the figure with switched subplots.
While this recreates the figure, you do not have to re-evaluate the function or script that originally created the figure.
PS: I'm not sure how new this feature is.

In addition to swapping the Position property of the axes objects, you could also swap the Parent property of the bar objects. This has the advantage of leaving your axes positioning intact.
A simple example:
function testcode
y1 = [2 2 3; 2 5 6; 2 8 9; 2 11 12];
y2 = -y1;
h(1) = subplot(1, 2, 1);
b(1,:) = bar(y1);
h(2) = subplot(1, 2, 2);
b(2,:) = bar(y2);
swapbar(h, b, [1,2]);
end
function swapbar(axesobjects, barobjects, axesswap)
set(barobjects(axesswap(1), :), 'Parent', axesobjects(axesswap(2)));
set(barobjects(axesswap(2), :), 'Parent', axesobjects(axesswap(1)));
end
Here I've created a small helper function swapbar to swap two axes. This isn't at all a robust implementation but it works well to illustrate the concept.
Old:
New:

Related

Matlab bars: changing the color of the bar and the space between bars and axes

I have a tricky question, which I think cannot be simply answered.
I have a large data table and want to save bar charts for each 2 corresponding mean values. I already did that with "for loop", but I cannot set different colors to my bars and cannot set proper spaces between bars and axes.
That's the simplest example:
k = [2 5]
bar(k)
Matlab thinks about those data [2 5] as about one "group" and it does not give a possibility of changing color for only one bar.
Of course, when we have different "groups", colors are changeable.
y = bar([1 2 3; 4 5 6]);
y(2).FaceColor = 'red';
But what about my example? I need only two bars, and I need to color them differently. Also, I want to set a small space between each bar and the axes (and again with two bars it is not that simple, and I cannot use "bar width" because that doesn't give me what I really want).
Does anyone know how to get around this?
Thanks for any reply!
Mary
A good trick could be add zero column for each group:
k = [2 5;0 0];
bar(k,'grouped')
UPDATE
Another solution to have different color could be using location in bar:
k = [2 5];
figure(1);
hold on;
h=bar(1,k(1));
set(h,'FaceColor','k');
h=bar(2,k(2));
set(h,'FaceColor','b');
hold off
As far as I know, this requires the use of a custom bar plot, since Matlab's barplots use dynamic colormaps. Personally, I like the GRAMM toolbox for all these customizations: [GRAMM on file-exchange] [GRAMM on github].
Here's an example:
x = [1 2];
y = [1 1.5];
c = x;
custom_map = ...
[1 0.3673 0.4132;
0 0.7375 0.8344];
clear g
g(1,1)=gramm('x',x,'y',y,'color',c);
g(1,1).geom_bar('width',0.2);
g(1,1).set_title('Width = 0.2');
g(1,2)=gramm('x',x,'y',y,'color',c);
g(1,2).geom_bar('width',0.8);
g(1,2).set_title('Width = 0.8');
g.set_names('y','','x','');
g.set_color_options('map',custom_map);
g.axe_property('YTick',[],'LineWidth',1,'YColor',[1 1 1],'XLim',[0.5 2.5],'XTick',[1 2])
figure('Position',[100 100 600 300]);
g.draw();
The histogram function is one option that will easily handle the spacing and x-axis labeling, but you'll have to plot each bar separately to independently control the colors:
k = [2 5];
histogram('Categories', {'ONE'}, 'BinCounts', k(1), 'BarWidth', 0.8, ...
'FaceAlpha', 1, 'FaceColor', [0 0.4470 0.7410]);
hold on;
histogram('Categories', {'TWO'}, 'BinCounts', k(2), 'BarWidth', 0.8, ...
'FaceAlpha', 1, 'FaceColor', [0.8500 0.3250 0.0980]);
Here is an option to workaround this. You can use diag(k) to create a 2*2 matrix with all zeros except the main diagonal that will be with your values, and Matlab will read it as 2 different groups. Then you change the Xdata of the 'dummy' bars (which you don't see but take some space on the x axis to nan so Matlab will ignore it.
k = [2 5];
b = bar(diag(k));
set(b,{'XData'},{[1 nan],[nan 1]}); % remove the group you don't want
set(gca,{'xticklabel','XTick'},{{'ONE','TWO'},[0.85 1.15]});
b(2).FaceColor = 'r'; % choose a different color
The result:
And if you want to generalize this to more groups (here it's 5):
k = 1:5;
data = diag(k);
xdata = eye(numel(k))./eye(numel(k)); % a martix of nan with 1 on the main diagonal
b = bar(diag(k));
% remove all data except one bin in all groups:
set(b,{'XData'},mat2cell(xdata,ones(size(data,1),1),size(data,2)))
X = xlim; 5 get x-axis limits
w = (1-X(1))/(numel(k)/2); % calculate the width of one bin
set(gca,'XTick',X(1)+w/2:w:X(2)) % set the X ticks to the center of the bins
set(gca,'xticklabel',{'ONE','TWO','THREE','FOUR','FIVE'}); % set the labels
set(b,{'FaceColor'},mat2cell(lines(numel(k)),ones(size(data,1),1),3)); % set the colors
and you get:
And finally, if you want them to 'hover' a little above the x-axis, you can add the following lines:
b(1).BaseLine.Color = 'none'; % remove the base line
ylim([-0.1 max(k(:))]) % shift the bars up a little
and get:

How do you plot a graph evolving over time?

I have data about a network showing edges and nodes such as:
edges = ...
[5 7 1;
5 7 2;
5 11 2;
5 7 3;
5 11 3;
5 16 3;
5 7 4;
5 11 4;
5 16 4;
5 21 4];
I'd like to obtain multiple different plots based on how those edges evolve because those edges are the result of a long observation (e.g. one year).
Each edge occurs at a different moment and therefore, I'd like to get those six different plots separately.
Suppose, the first month I see these edges:
edges = ...
[5 7 1];
And in the second month, I see this:
edges = ...
[5 7 2;
5 11 2;];
And month by month, more edges are added until the complete data set show above is obtained.
EDIT
The third column is the moment identifier and using this article (Filter Matrix by some column value
) I can loop through the matrix and obtain a filtered_edges to use in the graph() function.
END EDIT
The easy way would be to create different edges files and read them one by one, but is there a way to do this programmatically with Matlab?
See the mathworks documentation for details. For your case, here you go:
data = rand(6,2);
figure
% You need to somehow fix your axes, so that they don't resize
axis tight manual
ax = gca;
ax.NextPlot = 'replaceChildren';
% Let's record this to file
v = VideoWriter('myAnimation.avi');
v.FrameRate = 10; % slow down the animation
open(v);
loops = size(data,1);
F(loops) = struct('cdata',[],'colormap',[]); % Struct to hold frames
for i = 1:loops
plot(data(1:i,1),data(1:i,2),'*'); % plot what you want in the new frame
drawnow % clear and draw new frame
frame = getframe;
F(i) = frame; % if you want to animate locally you only need this
pause(0.1); % this just slows down locally, can be removed and does NOT influence the saved video
writeVideo(v,frame); % this is only if you want to save to file
end
close(v);

How do I add values to a vector when I do not have a subindex specified

I am working on a Bézier curve and this how my code looks right now
x=[3 2 6 4 1];
y=[8 1 7 5 9];
n=length(x)-1;
scatter(x,y)
hold on
for t=0:0.01:1
for i=0:1:n
xt=nchoosek(n,i)*(t^i)*(1-t)^(n-1)*x(n+1);
yt=nchoosek(n,i)*(t^i)*(1-t)^(n-1)*y(n+1);
end
end
plot(xt,yt)
hold off
I'm a beginner using Matlab so I'm experiencing some issues. I would like to know how to make xt and yt vectors of the same size as t (that means 101x1) and make the values they get while just i changes be added to the other values as long as t is the same. When t changes, they must start from 0 and add the values they get while just i changes until it gets to n.
Thank you
The variable xt and yt should be vectors and their tth value updated at each iteration of i. Try:
x=[3 2 6 4 1];
y=[8 1 7 5 9];
n=length(x)-1;
scatter(x,y)
hold on
T = 0:0.01:1
xt = zeros(size(T));
yt = zeros(size(T));
for idt = 1:length(T)
t=T(idt);
for i=0:1:n
xt(idt)=xt(idt)+nchoosek(n,i)*(t^i)*(1-t)^(n-i)*x(i);
yt(idt)=yt(idt)+nchoosek(n,i)*(t^i)*(1-t)^(n-i)*y(i);
end
end
plot(xt,yt)
hold off

Adding a curve to Matlab Figure

I have written a program that takes a lot of data and produces graphs.It would be really convenient and save me a lot of time if I could take curves on an existing figure and add their values together to make a single curve. For a simple example lets say I have the following code,
x = [0 1 2 3 4 5];
y = [0 1 2 3 4 5];
z = [4 6 2 8 7 9];
figure
plot(x,y,x,z)
This code will produce a figure with two curves. Without modifying the code or re-running the program, and only working with the figure options I would like to add the curve y + z to the plot. Is this possible? Thanks.
The reason I don't want to add the functionality is the plot code is buried within 8 loops
that calls data from a 4D cell array of file name strings.
If you have the x, y and z variable used in the plot you can just add new lines to the plot with
hold on
plot(x,y+z)
hold off
If you don't have them directly (they were generated in a function, for example, you can always get them from figure with XData, YData properties of line objects.
hline = findobj(gca,'type','line');
x = get(hline,'XData');
y = get(hline,'YData');
X = x{1}; % let's assume that all lines have the same x values.
Y = sum(cell2mat(y));
hold on
plot(X,Y)
hold off

Removing the line between two specific data points in Matlab

I am going to draw a graph in Matlab. The graph is quite simple and I am using the plot function.
Suppose the data that I want to plot is (0:1:10). I also put markers on my graph. Then, we have a line that has markers on coordinates (0,0),(1,1),(2,2),... etc.
Now, I want to remove the line between (2,2) and (3,3) without deleting the whole line. That is to say, my purpose is to get rid of a particular segment of the line without loosing the entire line or any marker points.
How can I do that?
Removing the section of line after you have plotted it is difficult. You can see that the line is made up of one MATLAB object by the following code:
x = 1:10;
y = 1:10;
H = plot(x, y, '-o');
get(H, 'children')
ans =
Empty matrix: 0-by-1
We can see that the line has no children, so there are no 'subparts' that we can remove. However, there are some cheeky tricks we can use to try to achieve the same effect.
Plot two lines separately
...using hold on. See Victor Hugo's answer. This is the proper way of achieving our goal.
Plot two separate lines in one
MATLAB doesn'y plot points with a NaN value. By modifying the input vectors, you can make MATLAB skip a point to give the effect of a broken line:
x = [0 1 2 2 3 4 5 6 7 8 9];
y = [0 1 2 nan 3 4 5 6 7 8 9];
plot(x, y, '-o');
This is equivalent to plotting a line from [0, 0] to [2, 2], skipping the next point, then starting again at [3, 3] and continuing to [9, 9].
'Erase' part of the line
This is the nastiest way of doing it, but is a cheap hack that could work if you can't be bothered with changing your input arrays. First plot the line:
x = 1:10; y = 1:10;
plot(x, y, '-o');
Now plot a white line over the part you wish to erase:
hold on
plot([2 3], [2 3], 'w');
As you can see, the result doesn't quite look right, and will respond badly if you try to do other things to the graph. In short, I wouldn't recommend this method but it might come in useful in desperate times!
Try the following:
y = [0.2751 0.2494 0.1480 0.2419 0.2385 0.1295 0.2346 0.1661 0.1111];
x = 1:numel(y);
plot(x(1:4), y(1:4), '-x')
hold
plot(x(5:end), y(5:end), '-x')