plotting two types of data on one graph

15 views (last 30 days)
Kitt
Kitt on 8 Oct 2024
Commented: Voss on 21 Oct 2024
This may not be possible but if anyone can figure it out, it's someone on here.
I have a matrix, 20 timesteps x 1000 individuals, and each element is either 1, 2, or NaN. I want to plot the number of 1 compared to 2 for each timestep.
However, I also have another vector, env, that is either 1, 2, 3, or 4 for each timestep. Is there anyway to also identify, at each timestep, not only the 1/2 count but also the env element as well?
For context, this is a patch choice model. An individual can either choose patch 1 (1) or patch 2 (2) or be dead (NaN). The environment (env) is changing between timesteps, with all combinations of patch 1 being good or bad and patch 2 being good or bad (1,2,3,4). I want to see how many individuals chose each patch and what states the patches were in at that time.
I'm envisioning something like this:
  4 Comments
Rahul
Rahul on 9 Oct 2024
Edited: Rahul on 9 Oct 2024
Hi @Kitt, I understood that you're trying to create a grouped bar graph with custom shading for each timestep. Although, the condition for shading or background color for a timestep using " ..with all combinations of patch 1 being good or bad and patch 2 being good or bad (1,2,3,4)" doesn't seem apparent, as in how are "good" or "bad" being defined based on the 'env' vector values. I've provided a sample snippet, that could resemble your solution:
% Initialize data (example setup)
data = randi([1 2], 20, 1000); % Replace with your actual data
data(rand(20, 1000) < 0.1) = NaN; % Insert some NaN values as example
env = randi([1 4], 1, 20); % Replace with your actual env vector
figure;
hold on;
for t = 1:20
% Count choices for path 1 and path 2, ignoring NaN values
count_path1 = sum(data(t, :) == 1);
count_path2 = sum(data(t, :) == 2);
% Plot bar for the current timestep
bar(t, [count_path1, count_path2]);
% Shading based on 'env' value
if env(t) == 1
color = [0.9, 0.9, 0.9];
elseif env(t) == 2
color = [0.8, 0.8, 1];
elseif env(t) == 3
color = [1, 0.8, 0.8];
else
color = [0.8, 1, 0.8];
end
% Add shading for the current timestep
fill([t-0.5 t-0.5 t+0.5 t+0.5], [0 1000 1000 0], color, 'FaceAlpha', 0.5, 'EdgeColor', 'none');
end
legend off;
% Custom legend for shaded regions (env values)
hGray = fill(NaN, NaN, [0.9, 0.9, 0.9], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hBlue = fill(NaN, NaN, [0.8, 0.8, 1], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hRed = fill(NaN, NaN, [1, 0.8, 0.8], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hGreen = fill(NaN, NaN, [0.8, 1, 0.8], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
% Create a custom legend for the shading colors
legend([hGray, hBlue, hRed, hGreen], {'Env = 1', 'Env = 2', 'Env = 3', 'Env = 4'}, 'Location', 'Best');
xlim([0 20])
xlabel('Timestep');
ylabel('Count of Individuals');
title('Individuals Choosing Path 1 and Path 2 Over Time');
hold off;
Here, the first bar in each of the group represents choice (1) and the latter choice (2). You can modify the conditions stating "Shading based on 'env' value" as per your use-case, to change the shading colors for each timestep.
Kitt
Kitt on 9 Oct 2024
This worked perfectly, thank you!
Sorry for not being more clear on the patch quality values; env =1 means that patch 1 is "good" and patch 2 is "bad", env = 2 means that patch 1 is "good" and patch 2 is "good", etc.
"good" and "bad" in these cases refer to the likelihood an individual is going to find food if they forage there. A higher chance of finding food means it's "good" and vice versa.

Sign in to comment.

Answers (2)

Rahul
Rahul on 16 Oct 2024
Hi @Kitt,
I understand that you're trying to create a grouped bar graph using timestep data with custom color shading of each bar group depending on values of another given array ‘env’, where the values indicate the following conditions:
env = 1 means that patch 1 is "good" and patch 2 is "bad",
env = 2 means that patch 1 is "good" and patch 2 is "good",
env = 3 means that patch 1 is "bad" and patch 2 is "bad",
env = 4 means that patch 1 is "bad" and patch 2 is "good",
You can iterate over each timestep and count choices of path “1” and “2” for all individuals in two vectors and then shade the respective region before plotting their grouped bars on the figure. Here’s how you can structure your code:
data = randi([1 2], 20, 1000); % Replace with your actual data
data(rand(20, 1000) < 0.1) = NaN; % Insert some NaN values as example
env = randi([1 4], 1, 20); % Replace with your actual env vector
figure;
hold on;
for t = 1:20
% Count choices for path 1 and path 2, ignoring NaN values
count_path1 = sum(data(t, :) == 1);
count_path2 = sum(data(t, :) == 2);
% Shading based on 'env' value
if env(t) == 1
color = [0.9, 0.9, 0.9];
elseif env(t) == 2
color = [0.8, 0.8, 1];
elseif env(t) == 3
color = [1, 0.8, 0.8];
else
color = [0.8, 1, 0.8];
end
% Add shading for the current timestep
fill([t-0.5 t-0.5 t+0.5 t+0.5], [0 1000 1000 0], color, 'FaceAlpha', 0.5, 'EdgeColor', 'none');
% Plot bar for the current timestep
b = bar(t, [count_path1, count_path2]);
b(1).FaceColor = 'b';
b(2).FaceColor = 'r';
end
legend off;
% Custom legend for shaded regions (env values)
hGray = fill(NaN, NaN, [0.9, 0.9, 0.9], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hBlue = fill(NaN, NaN, [0.8, 0.8, 1], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hRed = fill(NaN, NaN, [1, 0.8, 0.8], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hGreen = fill(NaN, NaN, [0.8, 1, 0.8], 'FaceAlpha', 0.5, 'EdgeColor', 'none');
% Create a custom legend for the shading colors
legend([hGray, hBlue, hRed, hGreen], {'patch 1 is "good" and patch 2 is "bad"', 'patch 1 is "good" and patch 2 is "good"', 'patch 1 is "bad" and patch 2 is "bad"', 'patch 1 is "bad" and patch 2 is "good"'});
xticks(0:20);
xlim([0 20])
xlabel('Timestep')
ylabel('Count of Individuals');
title('Individuals Choosing Path 1 and Path 2 Over Time');
hold off;
Here, the first bar in each group represents choice “1“ and the latter choice “2”. You can modify the conditions stating "Shading based on 'env' value" as per your use-case, to change the shading colors for each timestep.
For more information regarding the functions mentioned above, refer to the documentation links specified below:

Voss
Voss on 9 Oct 2024
% Initialize data (example setup)
data = randi([1 2], 20, 1000); % Replace with your actual data
data(rand(20, 1000) < 0.1) = NaN; % Insert some NaN values as example
env = randi([1 4], 1, 20); % Replace with your actual env vector
N = size(data,1);
t = 1:N;
figure
hold on
% Shading based on 'env' value
colors = [ ...
0 0 1; ...
0 0.6 0 ; ...
0.6 0 0.6; ...
0 0.8 0.8; ...
];
NC = 4;
hreg = cell(1,NC);
emptyhreg = false(1,NC);
for ii = 1:NC
if ~any(env == ii)
emptyhreg(ii) = true;
continue
end
hreg{ii} = xregion(t(env==ii)+0.5*[-1;1],'FaceColor',colors(ii,:),'FaceAlpha',1);
end
% Count choices for patch 1 and patch 2, ignoring NaN values
count_patch1 = sum(data == 1, 2);
count_patch2 = sum(data == 2, 2);
hbar = bar(t,[count_patch1, count_patch2],'EdgeColor','none');
hbar(1).FaceColor = 'r';
hbar(2).FaceColor = 'y';
xlim('tight')
xticks(t)
xlabel('timestep')
ylabel('# of individuals')
h = cellfun(@(x)x(1),hreg(~emptyhreg));
s = ["good","bad"];
idx = dec2bin(circshift(NC-1:-1:0,2),2)-'0'+1;
str = join("patch "+[1 2]+" "+s(idx),"/");
str = str(~emptyhreg);
h = [h hbar];
str = [str; "went to patch "+[1;2]];
legend(h,str,'Location','NorthOutside')
  1 Comment
Voss
Voss on 21 Oct 2024
@Kitt: If this answer worked for you, please "Accept" it. Thanks!

Sign in to comment.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!