Split Histogram - individual and total percentages display

5 vues (au cours des 30 derniers jours)
aine gormley
aine gormley le 4 Déc 2018
Commenté : Star Strider le 4 Déc 2018
Hello, I am trying to recreate something similar to the figure below. Currently, I can display the positive and negative in the respsective colours, but the code (also below) is coming up with the error "X must be same length as Y", which doesnt make sense to me with a histogram. Could someone help?
% Create 4D arrays that contain what is needed
TXxs = [];
TSAs = [];
% Loop through the five files - 001 to 005, read and save what is needed
num_files = 5;
for i = 1 : num_files
lat = ncread(sprintf('f.e122.F1850PDC5.f09_g16.control-io192.00%d_atm_h1_yearmean_selname.nc', i), 'lat');
lon = ncread(sprintf('f.e122.F1850PDC5.f09_g16.control-io192.00%d_atm_h1_yearmean_selname.nc', i), 'lon');
time = ncread(sprintf('f.e122.F1850PDC5.f09_g16.control-io192.00%d_atm_h1_yearmean_selname.nc', i), 'time');
TSA = ncread(sprintf('f.e122.F1850PDC5.f09_g16.control-io192.00%d_lnd_h1_yearmean_selname.nc', i), 'TSA');
TXx = ncread(sprintf('f.e122.F1850PDC5.f09_g16.control-io192.00%d_atm_h1_yearmean_selname.nc', i), 'TXx');
TXxs = cat(4, TXxs, TXx);
TSAs = cat(4, TSAs, TSA);
end
% Create storage for regression
% Number of lat and lon should be the same across all 5 files
% Also times should be the same
M = numel(lon);
N = numel(lat);
slope_TXx = zeros(M, N, num_files);
intercept_TXx = zeros(M, N, num_files);
slope_TSA = zeros(M, N, num_files);
intercept_TSA = zeros(M, N, num_files);
T = numel(time);
% Regress each lat/lon location
for i = 1 : M
for j = 1 : N
% Now go for each file
for k = 1 : num_files
% Get all time instances of each lat/lon location for TXx
y = squeeze(TXxs(i, j, :, k));
% Create regression problem and solve
x = [ones(T, 1) time];
%c = x \ y;
c = regress(y, x);
intercept_TXx(i, j, k) = c(1);
slope_TXx(i, j, k) = c(2);
% Repeat for TSA
y = squeeze(TSAs(i, j, :, k));
% Create regression problem and solve
%x = [ones(T, 1) time];
%c = x \ y;
c = regress(y, x);
intercept_TSA(i, j, k) = c(1);
slope_TSA(i, j, k) = c(2);
end
end
end
% Statistics work
% Unroll into a single vector and remove NaN values for TXx
slopes = slope_TXx(:);
slopes(isnan(slopes)) = [];
h=histogram(slopes(slopes>0));
h.FaceColor='red';
hold on
h1=histogram(slopes(slopes<0));
h1.FaceColor='blue';
ylim([0 11000]);
xlim([-0.0004 0.0005]);
title('Distribution of all M slopes - CTL TXx');
binranges = -0.0004:0.0005;
[bincounts] = h(x,binranges);
%Compute percent contributions
percentagevalues = bincounts./sum(bincounts) * 100;
%Create a histogram
figure
bar(binranges,bincounts,'h')
for i = 1:length(bincounts)-1
%Determine x location of label
x = (binranges(i) + binranges(i+1))/2;
%Determine y location of label, offset it by some distance from the
%top of the bar
y = bincounts(i)+1;
%Create a text object
text(x,y,num2str(bincounts(i),'%3.2f'),'HorizontalAlignment','center');
end
  2 commentaires
Adam Danz
Adam Danz le 4 Déc 2018
Which line is throwing the error?
aine gormley
aine gormley le 4 Déc 2018
Hi, it's
"for i = 1:length(bincounts)-1"

Connectez-vous pour commenter.

Réponses (1)

Star Strider
Star Strider le 4 Déc 2018
The problem is with your ‘binranges’ assignment. The colon (link) operator increments by default by 1, so the result of:
binranges = -0.0004:0.0005;
is:
binranges =
-0.0004
I would do this:
N = 10; % Number Of Bins
binranges = linspace(-0.0004, 0.0005, N);
or specify an increment step size:
binranges = -0.0004 : 0.0001 : 0.0005;
depending on the result you want.
  4 commentaires
aine gormley
aine gormley le 4 Déc 2018
hi,i so now i am just getting my normal histogram with the 2 colours (red positive, blue negative), but still not getting the percentage on either side.
or maybe there is a way I could just calculate the total percentrage on either side then overlay it myself?
Star Strider
Star Strider le 4 Déc 2018
You will need to calculate the percentages.
To display them as values on the top of each bar, this works:
y1 = [2 2 3; 2 5 6; 2 8 9; 2 11 12];
hBar = bar(y1,1); % Return ‘bar’ Handle
for k1 = 1:size(y1,2)
ctr(k1,:) = bsxfun(@plus, hBar(1).XData, hBar(k1).XOffset'); % Note: ‘XOffset’ Is An Undocumented Feature, This Selects The ‘bar’ Centres
ydt(k1,:) = hBar(k1).YData; % Individual Bar Heights
text(ctr(k1,:), ydt(k1,:), sprintfc('%.1f', log(ydt(k1,:))), 'HorizontalAlignment','center', 'VerticalAlignment','bottom', 'FontSize',8, 'Color','b')
end
It labels the top of each bar with the natural logarithm of the bar value, so you will need to adapt that to your percentages. (You can replace the sprintfc call with a compose call if you want.) I cannot run your code, so you will need to adapt it yourself. You will have to get the histogram counts and plot them as a bar plot for this to work. I am not certain it will work with a histogram plot (I’ve never tried it), although it might with a bit of ingenuity.

Connectez-vous pour commenter.

Produits


Version

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by