Reputation: 13876
Using Octave 4.2.1 on Windows with the qt
graphics toolkit (I can't use gnuplot
because it crashes in some other part of the code). I have a dataset which is 35x7x4 (35 data points for 7 conditions on 4 channels) - you can use random data for the purpose of this exercise.
I am trying to create 4 subplots (1 for each channel), with 7 bar graphs on each subplot (one per condition) to see how the distribution of data changes with each condition. Each of the 7x4 = 28 distributions has its own set of bins and frequencies, and I can't seem to be able to combine the 7 datasets on one graph (subplot).
Posting the whole of the code would be too complicated, but here's a simplified version:
nb_channels = 4;
nb_conditions = 7;
nbins = 15;
freq = zeros(nbins,nb_conditions,nb_channels);
xbin = zeros(nbins,nb_conditions,nb_channels);
plot_colours = [91 237 165 255 68 112 255;
155 125 165 192 114 173 0;
213 49 165 0 196 71 255];
plot_colours = plot_colours / 255;
for k = 1:nb_channels
for n = 1:nb_conditions
% some complex calculations to generate temp variable
[freq(:,n,k),xbin(:,n,k)] = hist(temp,nbins);
end
end
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
bar(xbin(:,n,k),freq(:,n,k),'FaceColor',plot_colours(:,n))
hold on
end
hold off
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
which gives something like this:
So you can't really see anything, all the bars are on top of each other. In addition, Octave doesn't support transparency property for patch objects (which is what bar charts use), so I can't overlay the histograms on top of each other, which I would really quite like to do.
Is there a better way to approach this? It seems that bar
will only accept a vector for x data and not a matrix, so I am stuck in having to use hold on
and loop through the various conditions, instead of using a matrix approach.
Upvotes: 1
Views: 2892
Reputation: 13876
OK, so I'll try to answer my own question based on the suggestions made in the comments:
This does improve the results somewhat but it's still an issue due to the lack of transparency for patch objects.
Code changes:
nbins = 15;
xbin = linspace(5.8,6.5,nbins);
for k = 1:nb_channels
for n = 1:nb_conditions
% some complex calculations to generate temp variable
freq_flow(:,n,k) = hist(temp,xbin);
end
end
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
bar(xbin,freq_flow(:,n,k),'FaceColor',plot_colours(:,n))
hold on
end
hold off
xlim([5.8 6.3])
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
Which gives the following plot:
This helps a bit more in terms of readability. However, the result is a bit "piece-wise".
Code changes:
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
plot(xbin,freq_flow(:,n,k),'LineStyle','none','marker','.',...
'markersize',12,'MarkerEdgeColor',plot_colours(:,n),...
'MarkerFaceColor',plot_colours(:,n))
hold on
end
hold off
xlim([5.8 6.3])
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
Which gives the following result:
The legend is a bit screwed but I can probably sort that out.
A variation on this I also tried was to plot just the points as markers, and then a fitted normal distribution on top. I won't post all the code here, but the result looks something like this:
Unfortunately, before I even got to the transparency workaround, gnuplot
keeps crashing when trying to plot the figure. There's something it doesn't like with subplots and legends I think (which is why I moved to qt
graphics toolkit in the first place, as I had exactly the same issue in other parts of the code).
I found this on SO: 3D histogram with gnuplot or octave
and used it as such:
figure
for k = 1:size(flow_factor,2)
subplot(2,2,k)
h = my_bar3(freq_flow(:,:,k));
fvcd = kron((1:numel(freq_flow(:,:,k)))', ones(6,1));
set(h, 'FaceVertexCData',fvcd, 'FaceColor','flat', 'CDataMapping','scaled')
colormap hsv; axis tight; view(50,25)
ylbl = cell(length(xbin),1);
for k=1:length(xbin)
ylb{k} = num2str(xbin(k));
end
set(gca,'YTick',1:2:nbins);
set(gca,'YTickLabel',ylb(1:2:end));
end
to produce:
Which isn't bad, but probably not as clear as the line plots.
On balance, I will probably end up using one of the line plots approaches, as they tend to be clearer.
Upvotes: 2