Plot one data set with two different units?

I have yet to find a satisfactory solution to how to plot 1 data set with two axis. Here is the plot I currently have:
So, what is happening is I am trying to plot scan rates of 2, 5, 10, 20, 50, and 100 mV/s. I am plotting the voltage on the x-axis and the Specific current in A/g on the y-axis. However, I also want to display the units in terms of A/cm^2 on the same graph. The data set is the same it just is using a different unit on the right y axis. I am using yyaxis but it plots the other data on the graph and adds it to the graph and legend.
I do not want the "data 1" plotted, I literally just want the right y-axis. Here is the code I am using:
mass=0.000547404; %grams
TotalArea=204.624/1000000;%meters^2
scanrate=[2 5 10 20 50 100];%mV/s
vWindow=0.5;%Volts
I = [2.74E-04 4.11E-04 5.47E-04 6.84E-04 1.37E-03]; %Amps at different GCD- ignore for this section- used later in a different section of code
%my file paths, you will have to change the file paths but I have attached
%the files
CVdataFiles={'Data\MXene\Electrode 2\CV Data 2mV_s.txt','Data\MXene\Electrode 2\CV Data 5mV_s.txt','Data\MXene\Electrode 2\CV Data 10mV_s.txt','Data\MXene\Electrode 2\CV Data 20mV_s.txt','Data\MXene\Electrode 2\CV Data 50mV_s.txt','Data\MXene\Electrode 2\CV Data 100mV_s.txt'};
%ignore these, they are so I dont have to change the files everytime I want
%to switch to another dataset.
%CVdataFiles={'Data\Device\MXene Symmetric Devices\Device 2\CV Data 2mV_s.txt','Data\Device\MXene Symmetric Devices\Device 2\CV Data 5mV_s.txt','Data\Device\MXene Symmetric Devices\Device 2\CV Data 10mV_s.txt','Data\Device\MXene Symmetric Devices\Device 2\CV Data 20mV_s.txt','Data\Device\MXene Symmetric Devices\Device 2\CV Data 50mV_s.txt','Data\Device\MXene Symmetric Devices\Device 2\CV Data 100mV_s.txt'};
%CVdataFiles={'Data\Device\MXene Symmetric Devices\On Celgard\Device 1\CV Data 2mV_s.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\CV Data 5mV_s.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\CV Data 10mV_s.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\CV Data 20mV_s.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\CV Data 50mV_s.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\CV Data 100mV_s.txt'};
%GCDDataFiles={'Data\MXene\Electrode 3\GCD 0.5 A_g.txt','Data\MXene\Electrode 3\GCD 0.75 A_g.txt','Data\MXene\Electrode 3\GCD 1 A_g.txt','Data\MXene\Electrode 3\GCD 1.25 A_g.txt','Data\MXene\Electrode 3\GCD 2.5 A_g.txt'};
%GCDDataFiles={'Data\Device\MXene Symmetric Devices\Device 2\GCD 0.025 A_g edit.txt','Data\Device\MXene Symmetric Devices\Device 2\GCD 0.05 A_g.txt','Data\Device\MXene Symmetric Devices\Device 2\GCD 0.1 A_g edit.txt','Data\Device\MXene Symmetric Devices\Device 2\GCD 0.25 A_g.txt','Data\Device\MXene Symmetric Devices\Device 2\GCD 0.5 A_g.txt'};
%GCDDataFiles={'Data\Device\MXene Symmetric Devices\On Celgard\Device 1\GCD 0.025 A_g.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\GCD 0.05 A_g.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\GCD 0.1 A_g.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\GCD 0.25 A_g.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\GCD 0.5 A_g.txt','Data\Device\MXene Symmetric Devices\On Celgard\Device 1\GCD 0.75 A_g.txt'};
CurrentDensity=[0.5 0.75 1 1.25 2.5];%Amps/gram
CurrentDensity_A=I./TotalArea;%Amps/meter^2
CVC = []; %Capacitance values from CV in Farads
CVC_g = []; %Capacitance values from CV in Farads/gram
CVC_A=[]; %Capacitance values from CV in Farads/Amps
CVAvCurrent=[]; %Average capacitance values from CV in Farads
thick=2;
figure(1)
CVtd=[]; %discharge time
CVED=[]; %energy density
CV100ED=[]; %E=1/2 cv^2- 100% efficient assumption
CV100PD=[]; %Power based off 100% efficient assumption
for t=1:6 %1:6 becuase 6 scan rates
file=string(CVdataFiles(t)); %Cycling thru data files
CVfile=importdata(file); %importing the data
CVdata=CVfile.data;
%Autolab potentiostat refusing to export data consistently. Column rows
%are not always the same but are either 13 or 14 in length. So I have
%split it into two if statements to process the data while accounting
%for the difference in file data column length.
if size(CVdata,2)== 13
ind=find(CVdata(:,12)==3); %finds cycle 3
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,10)./mass; %Calculates the Specific current in A/g
CVAvCurrent(end+1)=mean(CVCurrentDensity); %Calculates average A/g for later use in a table
CVACurrentDensity=CVdata(ind,10)./TotalArea; %Calculates the Specific current in A/cm^2
plot(CVdata(ind,11),CVCurrentDensity,"DisplayName",text,'LineWidth', thick); %Plots the voltage vs. A/g
hold on
for k= (1:10) %cycling thru all 10 cycles at each scan rate. i.e: cycle 1 at 2mV/s then cycle 2 at 2mv/s, etc.
ind1=find(CVdata(:,12)==k); %finding the cycle
area=trapz(CVdata(ind1,11),CVdata(ind1,10)); %capturing data under the curve
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow); %calculating capacitance
CVC_g(t,k)=CVC(t,k)/mass; %calculating specific capacitance in A/g
CVC_A(t,k)=CVC(t,k)/TotalArea; %calculating specific capacitance in A/cm^2
CVtd(t,k)=(CVdata(ind1(end-1),9)-CVdata(ind1(1),9))/2; %discharge time
CV100ED(t,k)=1/2*CVC_g(t,k)*vWindow*vWindow*1000/3600; %energy density calc
CV100PD(t,k)=CV100ED(t,k)/(CVtd(t,k)/3600); %power density calc
end
elseif size(CVdata,2)==14 %repeat above for the data sets with column length of 14
ind=find(CVdata(:,13)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,11)./mass;
CVAvCurrent(end+1)=mean(CVCurrentDensity);
CVACurrentDensity=CVdata(ind,11)./TotalArea;
%yyaxis left- I added that here in my previous attempts to get the
%data plotted on the right side but this is not working
plot(CVdata(ind,12),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,13)==k);
area=trapz(CVdata(ind1,12),CVdata(ind1,11));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;
CVtd(t,k)=(CVdata(ind1(end-1),10)-CVdata(ind1(1),10))/2;
CV100ED(t,k)=1/2*CVC_g(t,k)*vWindow*vWindow*1000/3600;
CV100PD(t,k)=CV100ED(t,k)/(CVtd(t,k)/3600);
end
end
end
%for table purposes later
standard=std(transpose(CVC_g));
AVG_CVC_g=mean(CVC_g,2);
% MAX_CVC_g=max(transpose(CVC_g));
% MIN_CVC_g=min(transpose(CVC_g));
% posError=transpose(MAX_CVC_g)-AVG_CVC_g;
% negError=transpose(MIN_CVC_g)-AVG_CVC_g;
%plot stuff
legend show
xlabel("Voltage (V)")
ylabel("Specific Current (A/g)")
%now for making the right side axis in A/cm^2-this produces the 2nd graph
%seen above- this is not right but am unsure how to fix it.
%yyaxis right
%pl=plot(CVdata(ind,11),CVACurrentDensity);
%ylabel('Specific Current (A/cm^-2)')
%axis equal; axis tight;
hold off
I hope the code and what I am trying to do is clear. If not, please dont hesitate to ask. I would really appreciate any help or suggestions. Thank you so much!
Respectfully,
Murray

 Accepted Answer

I do not understand the problem with the code, since it appears to work correctly and apparently produces the result you want. (I use readmatrix rather than importdata here.)
What else would you like it to do?
mass=0.000547404; %grams
TotalArea=204.624/1000000;%meters^2
scanrate=[2 5 10 20 50 100];%mV/s
vWindow=0.5;%Volts
%my file paths, you will have to change the file paths but I have attached
%the files
% CVdataFiles={'Data\MXene\Electrode 2\CV Data 2mV_s.txt','Data\MXene\Electrode 2\CV Data 5mV_s.txt','Data\MXene\Electrode 2\CV Data 10mV_s.txt','Data\MXene\Electrode 2\CV Data 20mV_s.txt','Data\MXene\Electrode 2\CV Data 50mV_s.txt','Data\MXene\Electrode 2\CV Data 100mV_s.txt'};
CVdataFiles = {'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070245/CV%20Data%2020mV_s.txt'; 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070250/CV%20Data%2050mV_s.txt'; 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070255/CV%20Data%20100mV_s.txt'}
CVdataFiles = 3×1 cell array
{'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070245/CV%20Data%2020mV_s.txt' } {'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070250/CV%20Data%2050mV_s.txt' } {'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070255/CV%20Data%20100mV_s.txt'}
CVC = [];
CVC_g = [];
CVC_A=[];
CVAvCurrent=[];
thick=2;
figure(1)
for t=1:size(CVdataFiles,1)
% file=string(CVdataFiles(t));
% CVfile=importdata(file);
% CVdata=CVfile.data;
CVdata = readmatrix(CVdataFiles{t});
if size(CVdata,2)== 13
ind=find(CVdata(:,12)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,10)./mass; %I want this as left axis
CVACurrentDensity=CVdata(ind,10)./TotalArea; %I want this to be right axis
plot(CVdata(ind,11),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,12)==k);
area=trapz(CVdata(ind1,11),CVdata(ind1,10));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;%F/m^2
end
elseif size(CVdata,2)==14
ind=find(CVdata(:,13)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,11)./mass;
CVACurrentDensity=CVdata(ind,11)./TotalArea;
%yyaxis left
plot(CVdata(ind,12),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,13)==k);
area=trapz(CVdata(ind1,12),CVdata(ind1,11));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;
end
end
end
legend('Location','best')
xlabel("Voltage (V)")
ylabel("Specific Current (A/g)")
%yyaxis right
%pl=plot(CVdata(ind,11),CVACurrentDensity);
%ylabel('Specific Current (A/cm^-2)')
%axis equal; axis tight;
hold off
.

6 Comments

Ashton Re
Ashton Re on 19 Jul 2022
Edited: Ashton Re on 19 Jul 2022
So I want that graph to have a right axis that displays the Specific current in A/cm^2. So I would like to add a right yaxis that uses the CVACurrentDensity. However, I dont want to plot the data twice. Does that makes sense?
That is what I am trying to do (I made this with the screenshot tool).
Try this —
mass=0.000547404; %grams
TotalArea=204.624/1000000;%meters^2
scanrate=[2 5 10 20 50 100];%mV/s
vWindow=0.5;%Volts
%my file paths, you will have to change the file paths but I have attached
%the files
% CVdataFiles={'Data\MXene\Electrode 2\CV Data 2mV_s.txt','Data\MXene\Electrode 2\CV Data 5mV_s.txt','Data\MXene\Electrode 2\CV Data 10mV_s.txt','Data\MXene\Electrode 2\CV Data 20mV_s.txt','Data\MXene\Electrode 2\CV Data 50mV_s.txt','Data\MXene\Electrode 2\CV Data 100mV_s.txt'};
CVdataFiles = {'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070245/CV%20Data%2020mV_s.txt'; 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070250/CV%20Data%2050mV_s.txt'; 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070255/CV%20Data%20100mV_s.txt'}
CVdataFiles = 3×1 cell array
{'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070245/CV%20Data%2020mV_s.txt' } {'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070250/CV%20Data%2050mV_s.txt' } {'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1070255/CV%20Data%20100mV_s.txt'}
CVC = [];
CVC_g = [];
CVC_A=[];
CVAvCurrent=[];
thick=2;
figure(1)
for t=1:size(CVdataFiles,1)
% file=string(CVdataFiles(t));
% CVfile=importdata(file);
% CVdata=CVfile.data;
CVdata = readmatrix(CVdataFiles{t});
if size(CVdata,2)== 13
ind=find(CVdata(:,12)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,10)./mass; %I want this as left axis
CVACurrentDensity=CVdata(ind,10)./TotalArea; %I want this to be right axis
plot(CVdata(ind,11),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,12)==k);
area=trapz(CVdata(ind1,11),CVdata(ind1,10));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;%F/m^2
end
elseif size(CVdata,2)==14
ind=find(CVdata(:,13)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,11)./mass;
CVACurrentDensity=CVdata(ind,11)./TotalArea;
%yyaxis left
plot(CVdata(ind,12),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,13)==k);
area=trapz(CVdata(ind1,12),CVdata(ind1,11));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;
end
end
end
Ax = gca;
Ax.YTick;
YAxRightValues = CVdata(ind,10)./TotalArea;
YAxRightTicks = linspace(min(YAxRightValues), max(YAxRightValues), numel(Ax.YTick));
YaxRightLabels = compose('%.4f x 10^7',YAxRightTicks/1E+7);
yyaxis right
% Ax.YAxis(2).TickValues
Ax.YAxis(2).TickLabels = YaxRightLabels;
Ax.YAxis(2).TickLabelColor = 'k';
legend('Location','best')
xlabel("Voltage (V)")
Ax.YAxis(1).Label.String = ("Specific Current (A/g)");
Ax.YAxis(2).Label.String = ("Specific Current (A/cm^2)");
Ax.YAxis(2).Label.Color = 'k';
Ax.YAxis(2).Color = 'k';
%yyaxis right
%pl=plot(CVdata(ind,11),CVACurrentDensity);
%ylabel('Specific Current (A/cm^-2)')
%axis equal; axis tight;
hold off
The 5-digit tick label precision is necessary because the values do not change much between them.
.
I think this is it but the values seem to be off.
Ax = gca;
Ax.YTick;
YAxRightValues = CVdata(ind,10)./TotalArea;
YAxRightTicks = linspace(min(YAxRightValues), max(YAxRightValues), numel(Ax.YTick));
YaxRightLabels = compose('%.4f x 10^7',YAxRightTicks/1E+7);%What is this doing?
From your code: min(YAxRightValues) should = -23.3031 and max(YAxRightValues)=21.9698
If thats the case then should the axis not have a corrosponding max and min value?
I believe something is going wrong in the line:
YaxRightLabels = compose('%.4f x 10^7',YAxRightTicks/1E+7);
Could you explain what is happening in this line for me?
From your code: min(YAxRightValues) should = -23.3031 and max(YAxRightValues)=21.9698
Your code is difficult to follow. I took my best guess as to what defined the axis ticks, taking my lead from this line:
CVACurrentDensity=CVdata(ind,10)./TotalArea; %I want this to be right axis
So I used those values to define the right y-axis tick labels:
YAxRightValues = CVdata(ind,10)./TotalArea;
since that line quite obviously defines them as the values you want for them.
If you want to define them differently, substitute the appropriate vector to define the ‘YAxRightValues’ vector. It may also be necessary to re-define the format string in the ‘YaxRightLabels’ definition.
I have no idea what vector to use for them, other than the one indicated in the code.
‘Could you explain what is happening in this line for me?
That creates a cell array of character vectors that define the right y-axis tick labels.
.
Ax = gca;
Ax.YTick;
YAxRightValues = CVdata(ind,10)./TotalArea;
YAxRightTicks = linspace(min(YAxRightValues), max(YAxRightValues), numel(Ax.YTick))
YaxRightLabels = compose('%.4f',YAxRightTicks);
yyaxis right
% Ax.YAxis(2).TickValues
Ax.YAxis(2).TickLabels = YaxRightLabels;
Ax.YAxis(2).TickLabelColor = 'k';
legend('Location','best')
xlabel("Voltage (V)")
Ax.YAxis(1).Label.String = ("Specific Current (A/g)");
Ax.YAxis(2).Label.String = ("Specific Current (A/cm^2)");
Ax.YAxis(2).Label.Color = 'k';
Ax.YAxis(2).Color = 'k';
hold off
This solved it. Just had to change the YaxRightLabels.
Thank you so so much Star Strider, your a god among men on this forum.
As always, my pleasure!
I very much appreciate your compliment!
.

Sign in to comment.

More Answers (2)

Jan
Jan on 19 Jul 2022
This is a lot of information and code, which has no relation to the actual problem. What exactly is the detail you want to change? The 7th entry in the legend? Where does it come from? Did it exist in the figure, before you run this code?
You mention, that you use yyaxis, but this is not part of the posted code. This means, that you run some other code. Then we cannot know, what happens there and it is possible, that the wanted changes have to be applied there.
Please explain clearly, what the problem is and post some minimal code, which reproduces the problem.

1 Comment

The exact detail I want to change is I want the graph to display this graph
just I want the right axis with a different unit without replotting the data. I.e want the left yaxis to be CVCurrentDensity and the right yaxis to be CVACurrentDensity
The 7th entry in the legend is what I am trying to get rid of. It get added when I run the code with the yyaxis. The yyaxis is in the code I just have it commented out. Here is a condensed version of the code
mass=0.000547404; %grams
TotalArea=204.624/1000000;%meters^2
scanrate=[2 5 10 20 50 100];%mV/s
vWindow=0.5;%Volts
%my file paths, you will have to change the file paths but I have attached
%the files
CVdataFiles={'Data\MXene\Electrode 2\CV Data 2mV_s.txt','Data\MXene\Electrode 2\CV Data 5mV_s.txt','Data\MXene\Electrode 2\CV Data 10mV_s.txt','Data\MXene\Electrode 2\CV Data 20mV_s.txt','Data\MXene\Electrode 2\CV Data 50mV_s.txt','Data\MXene\Electrode 2\CV Data 100mV_s.txt'};
CVC = [];
CVC_g = [];
CVC_A=[];
CVAvCurrent=[];
thick=2;
figure(1)
for t=1:6
file=string(CVdataFiles(t));
CVfile=importdata(file);
CVdata=CVfile.data;
if size(CVdata,2)== 13
ind=find(CVdata(:,12)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,10)./mass; %I want this as left axis
CVACurrentDensity=CVdata(ind,10)./TotalArea; %I want this to be right axis
plot(CVdata(ind,11),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,12)==k);
area=trapz(CVdata(ind1,11),CVdata(ind1,10));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;%F/m^2
end
elseif size(CVdata,2)==14
ind=find(CVdata(:,13)==3);
text=['Scan Rate ', num2str(scanrate(t)), ' mV/s'];
CVCurrentDensity=CVdata(ind,11)./mass;
CVACurrentDensity=CVdata(ind,11)./TotalArea;
%yyaxis left
plot(CVdata(ind,12),CVCurrentDensity,"DisplayName",text,'LineWidth', thick);
hold on
for k= (1:10)
ind1=find(CVdata(:,13)==k);
area=trapz(CVdata(ind1,12),CVdata(ind1,11));
CVC(t,k)=area./(2*((scanrate(t))/1000)*vWindow);
CVC_g(t,k)=CVC(t,k)/mass;
CVC_A(t,k)=CVC(t,k)/TotalArea;
end
end
end
legend show
xlabel("Voltage (V)")
ylabel("Specific Current (A/g)")
%yyaxis right
%pl=plot(CVdata(ind,11),CVACurrentDensity);
%ylabel('Specific Current (A/cm^-2)')
%axis equal; axis tight;
hold off
Does that help?

Sign in to comment.

Let's plot some sample data on the left axes.
yyaxis left
plot(1:10)
Now add a right axis.
yyaxis right
Change the Y limits, tick locations, and tick labels on the right axis.
ylim([1 10])
yticks(1:2:10)
yticklabels(string((1:2:10).^2))
If you're planning to zoom and/or pan in the axes, you're likely going to need to use the zoom mode object's and/or the pan mode object's ActionPostCallback to keep the ticks and tick labels of the two axes in sync.

Categories

Find more on 2-D and 3-D Plots in Help Center and File Exchange

Products

Release

R2021b

Community Treasure Hunt

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

Start Hunting!